1
usigned int x=1;
signed int y = -1;
double z = y * x * 0.25;

我正在使用 Microsoft Visual Studio 10 C++ 编译器。为什么 z 没有 -0.25 值?正如我从反汇编中看到的那样,它进行有符号整数乘法(imul),将 edx 的结果放在堆栈上,并用 0! 扩展它,因为它将是一个无符号整数。之后,它使用 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]

为什么有符号*无符号的乘法结果被解释为无符号?

4

3 回答 3

7

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

unsigned int当 an和 a相乘时signed int,两个操作数都被转换为unsigned int并且结果也是unsigned int由于 C 和 C++ 中算术表达式的整数转换规则,因此结果y * x将同时出现UINT_MAX - 1在 C 和 C++ 中。

无论您将示例编译为 C 还是 C++,您的示例都不会出现编译器错误。

于 2012-05-25T09:09:12.233 回答
5

这实际上是根据规范。C++11、5.9:

许多期望算术或枚举类型的操作数的二元运算符会导致转换并以类似的方式产生结果类型。目的是产生一个公共类型,这也是结果的类型。这种模式称为通常的算术转换,其定义如下:

[...]

否则,应在两个操作数上执行积分提升 (4.5)。然后将以下规则应用于提升的操作数:

[...]

  • 否则,如果无符号整数类型的操作数的秩大于或等于另一个操作数类型的秩,则将有符号整数类型的操作数转换为无符号整数类型的操作数的类型。

这里的两个操作数是y * x有符号整数和无符号整数,它们具有相等的整数转换等级;所以y最终被转换为无符号。

于 2012-05-25T09:07:37.007 回答
3

这在标准的 [expr] 部分中有描述:

……

否则,应在两个操作数上执行积分提升 (4.5)。然后将以下规则应用于提升的操作数:

— 如果两个操作数具有相同的类型,则不需要进一步转换。

— Otherwise, if both operands have signed integer types or both have unsigned integer types, the operand with the type of lesser integer conversion rank shall be converted to the type of the operand with greater rank.

— Otherwise, if the operand that has unsigned integer type has rank greater than or equal to the rank of the type of the other operand, the operand with signed integer type shall be converted to the type of the operand with unsigned integer type.

The expression is evaluated left to right and so y * x is calculated first. This has two integral types of the same rank, one operand signed and the other unsigned. Hence the signed value is converted to an unsigned value, as described in the final paragraph of the standards extract.

于 2012-05-25T09:09:39.293 回答