我最近遇到了一个关于我的C ++代码的问题让我想知道我是否对编译器对长操作有什么误解... 只需看看以下代码:
int
对于我来说,在这3行中的任何一行中发生乘法的顺序是不确定的。但是,这是我认为会发生的事情(假设long long
是32b,int
是64b,它们都遵循IEEE规则):
long long
s作为中间结果,导致溢出并存储-1073741824。对于最后一次乘法,此中间结果将提升为long long
,因此打印结果应为-5368709120。现在,对于第1行和第3行,我不确定:我认为虽然评估顺序未定义,但编译器会#34;促进"所有操作都是最大操作数的类型,即~/tmp$ g++-5 cast.cc
~/tmp$ ./a.out
-5368709120
-5368709120
16106127360
。因此,在这种情况下不会发生溢出,因为所有的计算都是在64b中进行的......但这就是GCC 5.3.0给我的代码:
{{1}}
我也期望第一个结果是16106127360。由于我怀疑在GCC中存在如此大规模的编译器错误,我猜错误在于键盘和主席之间。
任何人都可以确认/确认这是未定义的行为,并且GCC在给我任何它给出的任何内容时都是正确的(因为这是未定义的)?
答案 0 :(得分:7)
海湾合作委员会是正确的。
例如,第一个表达式被解析为i * j * k * n * l = ((((i * j) * k) * n) * l)
,并且只有在计算了最后一个乘法时才会进行提升,但此时左操作数已经不正确。
答案 1 :(得分:3)
标准明确地将分组定义如下:
5.6乘法运算符[expr.mul]
1乘法运算符*,/和%group从左到右。
这意味着a * b * c
被评估为(a * b) * c
。符合标准的编译器无权将其评估为a * (b * c)
。