Why is the output of this C code so unpredictable?
Posted by everydayreligion1090@reddit | learnprogramming | View on Reddit | 13 comments
#include <stdio.h>
int a = 1;
int fun(){
a = a * 2;
return a;
}
int main() {
int x = a + fun() + fun();
printf("%d", x);
return 0;
}
I tested this C code on Programiz and it consistently printed 8.
Thing is I got no idea how it's 8 because whether the expression is evaluated from the left or from the right, it just doesn't add up.
Does this depend on the compiler?
I would appreciate clarification on this.
aanzeijar@reddit
As others said, this is undefined behaviour in C, because you're modifying a multiple times in the same expression. The compiler is actually very graceful in giving you a number back at all, it would be allowed to delete your hard drive instead.
As for what actually happens, if you put the code into https://godbolt.org you can check with various compilers what the assembly ends up as.
With GCC on an x86 machine, it emits:
Which means:
Why is it allowed to reorder your expression for this? Because the C standard says that modifying a is undefined behaviour, so it may assume you do not do that.
DigitalMonsoon@reddit
So C is really fast, but part of that is that it doesn't run function calls in any kind of specificed order.
If you change it your code to this you should get your expected behavior
int val1 = fun(); // Runs first int val2 = fun(); // Runs second int x = a + val1 + val2; //Runs third
Willing_Whole6494@reddit
yeah the sequence points thing is what gets people, your global `a` gets modified during evaluation so order really matters here
PuzzleMeDo@reddit
I tested it on a different compiler and got the same result. It appears to have evaluated the middle 'fun()', then evaluated the a, then evaluated the fun() on the right. Giving 2 + 2 + 4.
Why is it doing it middle-out? I don't know. But it's not something I'd want to rely on.
zeekar@reddit
C doesn't necessarily evaluate expressions left-to-right or right-to-left; it might do middle-out or outside-in or any arbitrary order. In general the compiler will pick the order that generates the most efficient code.
am_Snowie@reddit
Dude you're literally modifying the global variable, by doing a = a * 2.
Winter-Volume-9601@reddit
To evaluate a + fun() requires the call to fun to happen first. When it does the value of a changes to 2. Then the add happens, and you get 2 + 2 + fun() with a=2 when fun is called the second time, returning 4.
So in the end you get 2 + 2 + 4 =8
ArcDotFish@reddit
I think OP understands this, their confusion stems from the fact that the result is 8 instead of 7 (if it were evaluated from left to right it would be 1 + 2 + 4 = 7 but it's obviously not doing that since the result is 8)
CappyRawr@reddit
It's unspecified behavior and you're modifying
aeach time you run it. It looks like the function calls are being run as asfun() + a + fun(), which is2 + 2 + 4_TheNoobPolice_@reddit
Golden rule of C. Don’t modify globals in expressions, expect weirdness.
ArcDotFish@reddit
Mathmatically, the order of operations for plus signs does not matter, e.g. a + b = b + a. You can't count in C evaluating it from left to right either, it will evaluate it in whatever order it deems more efficient. So this is just an example of a function with a side effect, and why such functions should generally be avoided.
IHoppo@reddit
A great example of why you shouldn't write code like that!
mkaypl@reddit
Looks like undefined behavior.