Reputation: 639
I am quite confused by the following code:
#include <stdio.h>
#include <stdint.h>
int main(int argc, char ** argv)
{
uint16_t a = 413;
uint16_t b = 64948;
fprintf(stdout, "%u\n", (a - b));
fprintf(stdout, "%u\n", ((uint16_t) (a - b)));
return 0;
}
That returns:
$ gcc -Wall test.c -o test
$ ./test
4294902761
1001
$
It seems that expression (a - b) has type uint32_t. I don't uderstand why since both operators are uint16_t.
Can anyone explain this to me?
Upvotes: 7
Views: 11974
Reputation: 70969
If you throw away the top-end bits of a number (by the explicit cast to a 16 bit unsigned integer) then you're going to have a result that is smaller (within the range of 0 and 2^16-1) than before.
Upvotes: 1
Reputation: 106317
The C standard explains this quite clearly (§6.5.6 Additive Operators):
If both operands have arithmetic type, the usual arithmetic conversions are performed on them.
(§6.3.1.8 Usual Arithmetic Conversions):
... the integer promotions are performed on both operands.
(§6.3.1.1 Boolean, characters, and integers):
If an
int
can represent all values of the original type, the value is converted to anint
; ... These are called the integer promotions. All other types are unchanged by the integer promotions.
Since int
can represent all values of uint16_t
on your platform, a
and b
are converted to int
before the subtraction is performed. The result has type int
, and is passed to printf
as an int
. You have specified the %u
formatter with an int
argument; strictly speaking this invokes undefined behavior, but on your platform the int
argument is interpreted as it's twos-complement representation, and that is printed.
Upvotes: 16
Reputation: 400129
C promotes the arguments to unsigned int
before doing the subtraction. This is standard behavior.
See, for instance, In a C expression where unsigned int and signed int are present, which type will be promoted to what type? for details.
Upvotes: 0