Integer Overflow in C
We have seen in previous lessons that integer types in C language have a minimum value and a maximum representable value.
But what happens if we try to exceed these limits? This condition is called Overflow and in this article we will see how the C language handles such condition.
The concept of Overflow
The processors of any system, whether it be a PC, a server, a tablet or a smartphone, are capable of performing mathematical operations on integer numbers.
In particular, modern processors are capable of performing operations on integer numbers of different sizes, such as 8, 16, 32 or 64 bit integer numbers.
There is a limit to such operations, which is given by the maximum size of the integer number that the processor is capable of representing.
For example, if the processor is 16 bit, the maximum representable integer number is
What happens when we try to add, using a 16 bit processor, the number
This condition is called Overflow. In Italian we could translate this term with straripamento or trabocco, precisely because the numerical value overflows from the maximum representable limit.
What happens when an Overflow occurs depends on the processor but in general the result will be an incorrect value, which does not correspond to the correct result of the operation.
Often, what happens is that the processor starts over counting from the minimum representable value. This value could be
Returning to the example above, if we try to add
The reason is that if we take the binary value of
The correct result should be:
that is a 1 followed by 16 zeros. But the processor is not capable of representing such value and therefore keeps exclusively the last 16 bits, which are all zeros:
The final effect results as if the processor had started counting from zero again: wrap around.
Recapping:
Overflow and Wraparound
An Overflow condition occurs when the result of a mathematical operation exceeds the maximum value representable by a processor.
In this case the result of the operation will be incorrect and, in most cases, the processor will start counting again from the minimum representable value. This behavior is called Wraparound.
In general, in case of overflow most processors signal, through appropriate mechanisms towards the operating system and the program itself, that this condition has occurred. However, not all programming languages handle this signaling in the same way.
For this reason, it is necessary to understand how the C language behaves in these situations.
Integer Overflow in C Language
In case of integer overflow, the C language assumes behaviors that differ depending on whether we are working with signed or unsigned integer numbers.
Let's start from the case of unsigned integers. Let's analyze the following program:
#include <stdio.h>
#include <stdint.h>
int main() {
uint32_t a = 4294967295;
a = a + 1;
printf("a = %u\n", a);
return 0;
}
The program declares a variable a of type uint32_t, that is an unsigned 32 bit integer. We initialize a to the maximum value representable by a 32 bit integer, that is
Subsequently, we add a with
If we execute the program, we will get:
a = 0
What happened is that the processor in overflow performed a wraparound simply returning 0. The program does not signal any error.
Now, let's try to slightly modify the program by adding to the variable, instead of 1, the value 10:
#include <stdio.h>
#include <stdint.h>
int main() {
uint32_t a = 4294967295;
a = a + 10;
printf("a = %u\n", a);
return 0;
}
If we execute the program, we will get:
a = 9
In this case too, the processor performed a wraparound, starting to count from 0 again. To be formally correct, what happened is that, if
This is the behavior dictated by the C standard in case of unsigned integer overflow.
Unsigned integer overflow in C
In C language, in case of unsigned integer overflow, the result of the operation will be the value obtained by performing a wraparound, that is starting to count again from the minimum representable value.
The result will be equal to the result of the operation modulo
This behavior is guaranteed by the C standard regardless of the processor or compiler.
Let's now move to the case of signed integers.
In this case, the C standard does not define a default behavior in case of overflow. This means that the behavior could vary from compiler to compiler and from processor to processor.
In general, most compilers and processors adopt the behavior of performing a wraparound, as in the case of unsigned integers.
As an example, let's try to execute the following program on a 64 bit x86 processor under the Linux operating system:
#include <stdio.h>
#include <stdint.h>
int main() {
int32_t a = 2147483647;
a = a + 1;
printf("a = %d\n", a);
return 0;
}
Trying to execute the program, we will get:
a = -2147483648
The obtained result is
Signed integer overflow in C
In C language, in case of signed integer overflow, a standard behavior is not defined. The behavior could vary from compiler to compiler and from processor to processor.
Most compilers, however, adopt the behavior of performing a wraparound, as in the case of unsigned integers.
In Summary
In this article we have seen what is meant by Overflow and how the C language handles this condition.
In particular, we have seen that:
- In case of unsigned integer overflow, the result of the operation will be the value obtained by performing a wraparound, that is starting to count again from the minimum representable value. The result will be equal to the result of the operation modulo
, where is the number of bits of the integer. - In case of signed integer overflow, a standard behavior is not defined. The behavior could vary from compiler to compiler and from processor to processor.