I've always taken this for granted before, but suppose I have:
uint8_t a;
uint8_t b;
if ((a - b) < 0) {
...
}
What is the data type of the expression (a - b)
? Mr. Godbolt tells me that it's a signed value; is that guaranteed by the any of the C specifications?
AMENDMENT:
I now understand that type promotion will guarantee that (a-b)
is an int when a and b are smaller than ints. What if instead a
and b
are unsigned int
s?
unsigned int a;
unsigned int b;
if ((a - b) < 0) {
...
}
CodePudding user response:
This expression will have type int
, which is signed.
Because both operands have a type smaller than int
, both will be promoted to type int
, and the result will have type int
.
Integer promotions are defined in section 6.3.1.1p2 of the C standard:
The following may be used in an expression wherever an
int
orunsigned int
may be used:
- An object or expression with an integer type (other than int or unsigned int) whose integer conversion rank is less than or equal to the rank of
int
andunsigned int
.- A bit-field of type
_Bool
,int
,signed int
, orunsigned int
.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. All other types are unchanged by the integer promotions.
So this means the expression ((a - b) < 0)
could potentially evaluate as true.
Had the variables been defined like this:
unsigned int a;
unsigned int b;
Then there would be no promotion and a - b
would have unsigned type, meaning ((a - b) < 0)
would always be false.