Search code examples
cif-statementexpressionimplicit-conversioninteger-promotion

Unsigned integer overflow in comparison expressions


In the C language, with this code snippet:

uint16_t a = 243;
uint16_t b = 65535;
uint16_t max = 65535;

if ((a + b) > max)
{
   printf("Out of range!");
}
else
{
   printf("Within range.");
}

The result will be "Out of range!". What type conversion rules apply in this case? Can someone point me to a documented source?

Thanks!


Solution

  • From the C Standard (6.5.6 Additive operators)

    4 If both operands have arithmetic type, the usual arithmetic conversions are performed on them.

    and (6.5.8 Relational operators)

    3 If both of the operands have arithmetic type, the usual arithmetic conversions are performed.

    and at last (6.3.1.8 Usual arithmetic conversions)

    1. ... Otherwise, the integer promotions are performed on both operands.

    and (6.3.1.1 Boolean, characters, and integers)

    2 The following may be used in an expression wherever an int or unsigned 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 and unsigned int. — A bit-field of type _Bool, int, signed int, or unsigned 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 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.

    So in the condition of the if statement

    if ((a + b) > max)
    

    all operands are converted to the type int according to the integer promotions. And an object of the type int is able to store the value of the integer expression a + b where each operand is in turn converted to the type int.

    In fact the above if statement you may imagine the following way

    if ( ( ( int )a + ( int )b ) > ( int )max )
    

    or like

    if ( ( ( unsigned int )a + ( unsigned int )b ) > ( unsigned int )max )
    

    depending on whether the type int or unsigned int can store the values of the type uint16_t.

    An overflow can occur if for example the size of the type int or unsigned int is the same as the size of the type uint16_t.