type promotion in C

Julien REINAULD picture Julien REINAULD · Oct 31, 2011 · Viewed 8.9k times · Source

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?

Answer

Stephen Canon picture Stephen Canon · Oct 31, 2011

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 an int; ... 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.