Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What happens when a integer overflow occurs in a C expression?

I have the following C code:

uint8_t firstValue = 111;
uint8_t secondValue = 145;
uint16_t temp = firstValue + secondValue;
if (temp > 0xFF) {
    return true;
}
return false;

This is the alternative implementation:

uint8_t firstValue = 111;
uint8_t secondValue = 145;
if (firstValue + secondValue > 0xFF) {
    return true;
}
return false;

The first example is obvious, the uint16_t type is big enough to contain the result. When I tried the second example with the clang compiler on OS/X, it correctly returned true. What happens there? Is there some sort of temporary, bigger type to contain the result?

like image 544
schuppentier Avatar asked Dec 15 '22 19:12

schuppentier


2 Answers

The operands of + are promoted to larger types, we can see this by going to draft C99 standard section 6.5.6 Additive operators which says:

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

and if we go to 6.3.1.8 Usual arithmetic conversions it says:

Otherwise, the integer promotions are performed on both operands.

and then we go to 6.3.1.1 Boolean, characters, and integers which says (emphasis mine):

If an int can represent all values of the original type, the value is converted to an int; otherwise, it is converted to an unsigned int. These are called the integer promotions.48) All other types are unchanged by the integer promotions.

So both operands of + in this case will be promoted to type int for the operation, so there is no overflow.

Note, Why must a short be converted to an int before arithmetic operations in C and C++? explains the rationale for promotions.

like image 110
Shafik Yaghmour Avatar answered Dec 31 '22 15:12

Shafik Yaghmour


The first example is obvious, the uint16_t type is big enough to contain the result.

In fact the destination lvalue x for the assignment x = expr; has no bearing on whether there is an overflow in expr. If there is, then the result is what it is regardless of how wide x is.

In your example, “integer promotions” apply and the computation is done between int operands. This means that there is no overflow. Integer promotions are described in C11 in clause 6.3.1.1:2.

If you had been adding two uint32_t values, then there could have been wrap-around (the specified behavior when an unsigned operation produces a result that is out of bounds for the unsigned type), even if the type of the lvalue to assign to result to was uint64_t.

like image 42
Pascal Cuoq Avatar answered Dec 31 '22 13:12

Pascal Cuoq