I have a problem. In this program the variable x should be set to 0x10000 but in both operations the result is 0.
This is not the main program but a test to find the reason for the error. I am currently making a 64 bit multiplier with hex input. I used 16-bit multiplication using Keil and Proteus
int main() {
unsigned long int x = 0;
x = 0x8000 * 0x2;
x = 0x8000 + 0x8000;
return 0;
}
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 anint
; otherwise, it is converted to anunsigned 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.