have a peek at this. The compiler is complaining that I have an integer overflow, but when I look at the C89 standard's rules for integral promotion along with the values in that expression, it seems to me that there is no overflow.
rutski@imac:~$ cat test.c
#include <stdio.h>
#include <inttypes.h>
const uint32_t value =
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256) +
(0xDF-0xC2 + 1) * (256 + 256*256 + 256*256*256);
int
main(void)
{
printf("value = %"PRIu32"\n", value);
return 0;
}
rutski@imac:~$ gcc -std=c89 -pedantic -Wall -Wextra test.c
test.c:5: warning: integer overflow in expression
test.c:6: warning: integer overflow in expression
test.c:6: warning: overflow in constant expression
rutski@imac:~$ ./a.out
value = 2661195264
rutski@imac:~$
Moreover, google confirms that the answer of 2661195264 is the correct value for that expression! (See this link)
So, how is it that the program can produce a correct value when there was integer overflow? And more importantly, how is it that there was integer overflow in that expression to begin with?
(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).
Integer Overflow is a phenomenon that occurs when the integer data type cannot hold the actual value of a variable. Integer Overflow and Integer Underflow in C, do not raise any errors, but the program continues to execute (with the incorrect values) as if nothing has happened.
There are two ways to get around this: Cast the numbers to a bigger integer type, then do the addition there, and check if the result is in the right range. Do the addition normally, then check the result (e.g. if (a+23<23) 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.
(0x7F-0x00 + 1) * (256 + 256*256 + 256*256*256)
has the value 2155905024
; the largest representable signed 32-bit int
is 2147483647
, so you have indeed produced an overflow. It happens to have given you the expected result anyway (you got lucky).
Note that your entire initializer has signed type (type int
, specifically), as none of the literals are suffixed. The expression is evaluated as a signed int, then the resulting value is converted to an unsigned integer.
Although your constants are all positive, they are still signed integers. You are overflowing the range of a signed integer. The result is converted to unsigned as the last step when it is assigned to the variable.
The bit patterns for addition, subtraction, and multiplication are identical between signed and unsigned operations. While the compiler is not required to provide the correct answer in this case, it's just the most natural result.
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