GENERAL: #DEFINES WITH ARITHMETIC DON'T WORK
Information in this article applies to:
I use the following #defines to create the constants I use in my program:
#define AAA 1042 #define BBB (1023 * AAA)
When I use BBB in my program, the result I get is around 17,000 instead of 1,065,966 which is what I expect. What is going on? Why does the compiler generate the wrong value?
This explanation requires use of ANSI C Standard. Note that this is not a bug in the compiler. This code yields the same results in any C compiler where an int type occupies 16 bits.
Here are some interesting things about the ANSI C specification as it applies to our compiler and the code above.
These three points are by ANSI specification paragraph 18.104.22.168 "Usual Arithmetic Conversions" which states the following (this is paraphrased!):
The rules are...
AND SO ON...
Remember that the result has the SAME TYPE as the operands. So, if the compiler thinks the operands are ints (16-bit), the result is an int (16-bit). Even if the result of the operation overflows!
Now, we can see that 1023 * 1042 generates a value that cannot be represented in 16-bits. However, ANY C COMPILER that conforms to the ANSI standard will calculate this number as...
1042 * 1023 = 1065966 (0x001043EE) (This is a 32-bit value which is truncated into a 16-bit int.)
Then, when the compiler correctly truncates this value to a 16-bit value, we get 0x43EE or 17,390 in decimal. Note that this is the value that is observed by the engineer. And this is what is specified by rule J above.
The solution is to convert at least one of the operands to a long. Therefore, the result will be a long according to rule G listed above. You may convert both constants to long integers if that makes you feel more comfortable! Rule G still applies.
In our example, to have the compiler implicitly cast the value of BBB to a LONG, either of the integer numeric constants (1042 or 1023) must be a long. The letter L following the number indicates (in C) that the value is a long integer type.
For example, the following code generates the expected results.
#define AAA 1042 #define BBB (1023L * AAA)
If you run into this problem while porting existing code, the original target probably defined ints to be 32-bits. If this is the problem, you should convert all numeric constants to long ints by adding the L suffix.
The following Discussion Forum threads may provide information related to this topic.
Last Reviewed: Tuesday, December 18, 2007
of your data.