Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C integer overflow behaviour when assigning to larger-width integers

If I execute the following code in C:

#include <stdint.h>

uint16_t a = 4000;
uint16_t b = 8000;

int32_t c = a - b;

printf("%d", c);

It correctly prints '-4000' as the result. However, I'm a little confused: shouldn't there be an arithmetic overflow when subtracting a larger unsigned integer from the other? What casting rules are at play here? This question seems a bit noobish, so any references would be greatly appreciated.

like image 827
Davorian Avatar asked Apr 08 '09 07:04

Davorian


People also ask

How does C handle integer overflow?

In C programming language, a computation of unsigned integer values can never overflow, this means that UINT_MAX + 1 yields zero. More precise, according to the C standard unsigned integer operations do wrap around, the C Standard, 6.2.

What happens if we assign an integer value to a variable that is too large for that variable to hold?

(Arithmetic) Integer Overflows An integer overflow occurs when you attempt to store inside an integer variable a value that is larger than the maximum value the variable can hold. The C standard defines this situation as undefined behavior (meaning that anything might happen).

What can we do to avoid overflow errors if we need to deal with large numbers?

look into bignum arithmetic libraries. they'll be a bit slower than standard C arithmetic but at least you won't get overflow. also many standard math functions (exp etc) will set errno to ERANGE in case of overflow. Usually, it is prevented by thinking carefully when writing code.

Which type of overflow happens when int exceeds value?

Integer overflow, also known as wraparound, occurs when an arithmetic operation outputs a numeric value that falls outside allocated memory space or overflows the range of the given value of the integer.


3 Answers

The issue is actually somewhat complicated. Operands of arithmetic expressions are converted using specific rules that you can see in Section 3.2.1.5 of the Standard (C89). In your case, the answer depends on what the type uint16_t is. If it is smaller than int, say short int, then the operands are converted to int and you get -4000, but on a 16-bit system, uint16_t could be unsigned int and conversion to a signed type would not happen automatically.

like image 181
TrayMan Avatar answered Nov 14 '22 20:11

TrayMan


The short answer is that these are all promoted to int during the subtraction. For the long answer, look at section 6.3.1.1 of the C standard, where it talks about integer promotions in arithmetic expressions. Relevant language from the standard:

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. All other types are unchanged by the integer promotions.

The details are in there, too, but they get pretty nasty.

like image 44
Todd Gamblin Avatar answered Nov 14 '22 20:11

Todd Gamblin


Both operands are promoted to int32_t during the subtraction. If the result had been larger than the maximum value for int32_t you would've seen overflow.

like image 34
dirkgently Avatar answered Nov 14 '22 21:11

dirkgently