一元:为什么一元在 c# 中的行为因 c/c++ 而异
Unary: Why unary's behavior in c# varies with c/c++
可能重复:
未定义、未指定和实现定义的行为
未定义的行为和序列点
Pre&C、C++、Java和&C#
我有这个代码片段:
int x = 2;
int y = x + 4 * ++x;
// what is y???
当我在c/c++中编译和测试它时,我会得到:
// C/C++
y is 15
但是通过c#我会得到
// C#
y is 14
为什么
IL的一部分是:
locals init ([0] int32 x,
[1] int32 y)
IL_0000: nop
IL_0001: ldc.i4.2
IL_0002: stloc.0
IL_0003: ldloc.0
IL_0004: ldc.i4.4
IL_0005: ldloc.0
IL_0006: ldc.i4.1
IL_0007: add
IL_0008: dup
IL_0009: stloc.0
IL_000a: mul
IL_000b: add
IL_000c: stloc.1
IL_000d: ldloca.s y
int y = x + 4 * ++x;
在C和C++中,每个操作数的求值顺序是未指定的,这意味着x
或4*++x
可以在另一个之前求值。由于操作数的求值顺序未指定,因此整个表达式的结果也未指定。
如果在4*++x
之前评估x
,则y
将计算为:
int y = x + 4 * ++x; //original
int y = 2 + 4 * ++x //evaluate x first
= 2 + (4 * 3) //evaluate 4 *++x then
= 14;
类似地,如果在x
之前评估4*++x
,则
int y = x + 4 * ++x; //original
int y = x + (4*3) //evaluate 4 * ++x first
= 3 + 12 //evaluate x then (x is incremented)
= 15;
在C#中,操作数需要从左到右求值,因此您总是得到第一个行为,结果为14。
实际上,在C++中,您只会得到未定义的行为,因为表达式的求值顺序并不总是指定的,所以不清楚第一次使用x读取的是旧值还是新值。两者都是可能的,事实上,任何事情都有可能,因为标准明确规定了发生的事情是不确定的。
C#作为一种安全的语言,不允许出现这种情况,因此更严格地定义了求值顺序。
相关文章:
- C++ 代码的行为因编译器而异
- 随机数生成器的性能因平台而异
- 班级大小因模块 (DLL) 而异.如何以及为什么?
- 虚拟指针大小因类数据成员而异
- 包含标头中的搜索路径因编译器而异
- 为什么汇编代码因我使用的反汇编程序而异
- 以下代码的输出是什么(答案因差异编译器而异)
- 引用基类的 constexpr 构造函数因编译器而异
- 分段故障位置因 printf 而异
- 重新解释的值因编译器而异
- sizeof(std::list<T>) 可以因不同类型的 T 而异吗?
- 如何引用要以C++打开的文件,因为其完整路径名将因计算机而异
- C++ 静态成员函数错误 C2556 重载函数仅因返回类型而异
- 强制转换函数指针,该指针因参数类型而异
- 未使用的变量警告因自动变量而异
- UDP数据包丢失因数据包大小而异
- 浮点常量值因C++声明方式而异(Xcode IDE)
- 模板方法,其参数数量为实例化固定,但因模板参数而异
- 套接字连接超时因网络而异
- 一元:为什么一元在 c# 中的行为因 c/c++ 而异