Microsoft C ++编译器有错误吗?

时间:2012-05-25 09:01:04

标签: c++ visual-studio-2010 visual-c++

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的乘法结果被解释为无符号?

3 个答案:

答案 0 :(得分:7)

表达式y * x * 0.25在C和C ++中与(y * x) * 0.25关联。

当将unsigned intsigned 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。这有两个相同等级的整数类型,一个操作数已签名,另一个未签名。因此,有符号值将转换为无符号值,如标准摘录的最后一段所述。