Unsigned integer overflow in comparison expressions

689 views Asked by At

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!

2

There are 2 answers

0
Vlad from Moscow On BEST ANSWER

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.

1
Eric Postpischil On

If int is wider than 17 bits, a, b, and max will be converted to int. a + b will not overflow and will yield a result greater than max.

If int is 17 bits wide, a, b, and max will be converted to int. a + b will overflow, and the behavior is not defined by the C standard.

If int is 16 bits wide, a, b, and max will not be converted. a + b will wrap and will yield a result less than max.