asu
asu

Reputation: 569

Microsoft C++ compiler have a bug?

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

I'm using Microsoft Visual Studio 10 C++ compiler. Why z don't have -0.25 value? As I saw from disassembly, it makes an signed int multiply (imul), places the result from edx on the stack, and extends it with 0!, as it would be an unsigned int. After that it multiplies it using FP instructions.

.............
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]

Why the result of multiply of signed * unsigned is interpreted as unsigned?

Upvotes: 1

Views: 460

Answers (3)

Jon
Jon

Reputation: 437326

This is actually according to the spec. C++11, 5.9:

Many binary operators that expect operands of arithmetic or enumeration type cause conversions and yield result types in a similar way. The purpose is to yield a common type, which is also the type of the result. This pattern is called the usual arithmetic conversions, which are defined as follows:

[...]

Otherwise, the integral promotions (4.5) shall be performed on both operands. Then the following rules shall be applied to the promoted operands:

[...]

  • 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.

Here the two operands in y * x are signed and unsigned int, which have an equal integer conversion rank; so y ends up being converted to unsigned.

Upvotes: 5

David Heffernan
David Heffernan

Reputation: 612794

This is described in the [expr] section of the standard:

....

Otherwise, the integral promotions (4.5) shall be performed on both operands. Then the following rules shall be applied to the promoted operands:

— If both operands have the same type, no further conversion is needed.

— 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.

Upvotes: 3

CB Bailey
CB Bailey

Reputation: 791361

The expression y * x * 0.25 associates as (y * x) * 0.25 in both C and C++.

When multiplying an unsigned int and a signed int, both operands are converted to unsigned int and the results is also an unsigned int due to the integer conversion rules for arithmetic expressions in both C and C++ so the result of y * x will be UINT_MAX - 1 in both C and C++.

Your example doesn't exhibit a compiler bug whether you are compiling your example as C or C++.

Upvotes: 7

Related Questions