PRB: Type Conversion from unsigned long to double Incorrect

ID Number: Q72478

6.00 6.00a 6.00ax | 6.00 6.00a

MS-DOS | OS/2

buglist6.00 buglist6.00a buglist6.00ax fixlist7.00

Summary:

SYMPTOMS

In Microsoft C versions 6.0, 6.0a, and 6.0ax, when the result of an

unsigned long calculation is converted to a double, incorrect

results may be generated.

RESOLUTION

The sample program below is the complete example that demonstrates

the error. The following methods may be used to work around the

problem:

- Use the /qc option on the command line because the quick

compiler generates the correct code for this case.

-or-

- Either change the type of the variables a and b to signed long,

or apply a cast to long in the calculation.

-or-

- Cast one of the arguments to double. This will force the

compiler to convert to double before performing the calculation.

STATUS

Microsoft has confirmed this to be a problem in C versions 6.0,

6.0a, and 6.0ax. This problem was corrected in C/C++ version 7.0.

More Information:

The following code fragment illustrates this problem:

unsigned long a = 4, b = 3;

double result;

result -= a - b;

When this code is compiled with the quick compiler (/qc option), the

code generated sets result equal to -1.0. On the other hand, compiling

with the full optimizing compiler generates code that sets result to

4,294,967,295.0.

The problem is that the full optimizing compiler evaluates the

expression "result -= a-b" as "result = result+(b-a)". This, in

itself, is not incorrect. However, when the compiler goes to convert

the value from unsigned long to double, it treats the result as an

unsigned value (which it once was) instead of a signed value (which it

now is).

The quick compiler generates the correct code because it doesn't

perform the original algebraic optimization.

Sample Code

-----------

/* Compile options needed: none

*/

#include <stdio.h>

void main(void)

{

unsigned long a = 4;

unsigned long b = 3;

double result = 0.0;

result -= a - b;

printf( "Result should be -1.0 : %lf\n", result);

}

Additional reference words: 6.00 6.00a 6.00ax