The literal 0x8000
is of type unsigned int
. On your 16-bit machine, the int
and therefore unsigned int
is of the natural size of 16 bits, the smallest accepted by the C standard. The integer promotion rules say that the smaller width types are widened to int
or unsigned int
, but no further (C11 n1570 6.3.1.1p2):
If an int
can represent all values of the original type (as restricted by the width, for a bit-field), the value is converted to an int
; otherwise, it is converted to an unsigned int
. These are called the integer promotions. 58) All other types are unchanged by the integer promotions.
An operand is widened from int
or unsigned int
only if the other operand has a greater rank.
Here, 0x8000
+ 0x8000
is calculated using unsigned int
which will wrap to 0, because the maximum value that can be represented in unsigned int
is 0xFFFF
.
You should force at least one of the operands to unsigned long
using either the suffix UL
, or by adding an explicit cast:
int main() {
unsigned long int x=0;
/* unsigned long int * int */
x = 0x8000UL * 0x2;
/* unsigned long + unsigned int */
x = (unsigned long)0x8000 + 0x8000;
return 0;
}
See also In a C expression where unsigned int and signed int are present, which type will be promoted to what type? for general discussion.