usigned int x=1;
signed int y = -1;
double z = y * x * 0.25;
我正在使用Microsoft Visual Studio 10 C ++编译器。 为什么z没有-0.25值? 正如我从反汇编中看到的那样,它使得一个有符号的int乘法(imul),将edx的结果放在堆栈上,并用0!扩展它,因为它将是一个unsigned int。之后,它使用FP指令将其相乘。
.............
imul edx,dword ptr [ecx]
mov dword ptr [ebp-98h],edx
mov dword ptr [ebp-94h],0
fild dword ptr [ebp-98h]
fmul qword ptr [__real@3fd0000000000000 (1402FB8h)]
fstp qword ptr [z]
为什么signed * unsigned的乘法结果被解释为无符号?
答案 0 :(得分:7)
表达式y * x * 0.25
在C和C ++中与(y * x) * 0.25
关联。
当将unsigned int
和signed int
相乘时,两个操作数都会转换为unsigned int
,并且由于算术表达式的整数转换规则,结果也是unsigned int
在C和C ++中,{C}和C ++中y * x
的结果都是UINT_MAX - 1
。
无论您是将示例编译为C还是C ++,您的示例都不会出现编译器错误。
答案 1 :(得分:5)
这实际上是根据规范。 C ++ 11,5.9:
许多期望算术或算术操作数的二元运算符 枚举类型导致转换并产生类似的结果类型 办法。目的是产生一种普通类型,它也是一种类型 结果。这种模式称为通常的算术转换, 其定义如下:
[...]
否则,应对两者进行整体促销(4.5) 操作数。然后,以下规则适用于晋升 操作数:
[...]
- 否则,如果具有无符号整数类型的操作数具有等级 大于或等于另一个操作数类型的等级, 带有符号整数类型的操作数应转换为类型 带有无符号整数类型的操作数。
这里y * x
中的两个操作数是有符号且无符号的int,它们具有相等的integer conversion rank;所以y
最终会被转换为无符号。
答案 2 :(得分:3)
标准的[expr]部分对此进行了描述:
...
否则,应对两者进行整体促销(4.5) 操作数。然后,以下规则适用于晋升 操作数:
- 如果两个操作数具有相同的类型,则不再进一步转换 需要。
- 否则,如果两个操作数都有有符号整数类型或 两者都有无符号整数类型,操作数类型较小 整数转换等级应转换为操作数的类型 排名更高。
- 否则,如果操作数有无符号 整数类型的排名大于或等于类型的排名 另一个操作数,带有符号整数类型的操作数应为 转换为带无符号整数类型的操作数类型。
从左到右评估表达式,因此首先计算y * x
。这有两个相同等级的整数类型,一个操作数已签名,另一个未签名。因此,有符号值将转换为无符号值,如标准摘录的最后一段所述。