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.
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.
(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).
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.
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.
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.
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 anint
; otherwise, it is converted to anunsigned 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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With