My Favourite Programming Language
As hopefully many people are aware, C and C++ have a notion of “Undefined Behaviour”. Few people seem to realize what that means though, so I wanted to write a funny program to illustrate it.
Most people just seem to think that if Undefined Behaviour happens, then just some values might be random. However, I think it’s much worse than that.
At the moment I am using gcc version 13.1.1 20230429, so if you want to reproduce results I would recommend sticking to that (or very similar) compiler versions.
Let’s get started then! One of the simplest undefined behaviours in the C language family is integer overflow. Now one might think: if overflow occurs, the value of the variable that has overflow just isn’t defined - however, that couldn’t be further from the truth.
What the C compiler internally does, is that it assumes that undefined behaviour never occurs. What makes this dangerous is that those assumptions are then used to optimize your code.
Let me give an example:
#include <stdio.h>
int main(void) {
int i = 0x40000000;
printf("3*i has the value %d.\n", 3*i);
return 0;
}
Because integer overflow is a thing, this prints the following line:
3*i has the value -1073741824.
However, as mentioned before, the compiler assumes that this does not happen. And this is exactly the problem:
#include <stdio.h>
int main(void) {
int i = 0x40000000;
printf("3*i has the value %d.\n", 3*i);
if (3 * i > 0) {
printf("3*i is bigger than zero.\n");
}
return 0;
}
Surprisingly, this snippet prints both lines! First, it prints the (negative) value of 3 times i, and then it claims that the value is positive!
That is due to a simple optimization of gcc that tries to prevent expensive conditional jumps, and so decides at compile time that multiplying two positive numbers is also positive - assuming integer overflow does not happpen.
This can cause very funny (and hard to debug) errors, which is why C is sadly not my favourite language. I hope you learned something in this short blogpost :)
#include <stdio.h>
int main(void) {
int i = 0x40000000;
int k1 = 3 * i;
#define k2 3 * i
if (k1 < 0 && k2 > 0 && k1 == k2) {
printf("totally sane language\n");
}
return 0;
}