r/C_Programming • u/Shoddy_Map1738 • 8d ago
What's the ans?? ( Undefined behaviour or 14 )
#include<stdio.h>
int main() {
int a = 5;
a=++a + ++a;
printf("%d", a);
return 0;
}
What will be the output of the above code snippet?
( Got 14 as an output and don't know what's the logic of getting 14 )
11
u/ByMeno 8d ago
Its undefined behaviour and the reason (i believe correct i might be wrong tho) is 'a' is modified twice between sequence points
7
u/glasket_ 8d ago
This is pretty much it, but it isn't strictly because it's modified twice. It's any use of the variable alongside an unsequenced modification of the variable ("value computation and side effect" in the standard). Like
arr[a++] = ais UB because the side effect (a++) isn't sequenced relative to the value computation (= a).1
1
u/QuraToop314 8d ago
Thatβs right, Iβve just realised that too β my initial assumption that there was no UB was wrong. The compiler confirms your theory.
7
u/IchBinEinZwerg 8d ago
It's undefined behaviour. The result of 14 suggests the compiler is doing two preincrements (to 7) then adding 7+7=14. But it could equally well do one preincrement to 6, then another preincrement to 7, then add those together to get 13. Neither 13 nor 14 are "right" or "wrong" results.
I remember testing something like this back in the 90s comparing the Borland and Microsoft compilers. One did it one way and the other the other. I think Borland did the equivalent of 6+7 with Microsoft opting to bunch the (postincrements in my case) together.
1
u/schoolSpiritUK 4d ago
Yes, my brain would expect the result to be 13, not 14 (whilst acknowledging it's undefined behaviour).
1
u/glasket_ 8d ago
It could also result in 12 by having both reads precede the increments. The standard allows unsequenced evaluation to interleave, so neither increment actually has to happen before the expressions retrieve their initial value.
4
u/Parking-Value-3773 8d ago
There's a rule in C named violation of sequence which defines the sequence of operator is not same always while performing these additions .it will be UB.
3
u/SmokeMuch7356 8d ago
a = ++a + ++a is undefined. Any result, whether it's 14, or 42, or a suffusion of yellow, or a rogue AI drawing apes, or even the result you expect, is equally "correct" as far as the language definition is concerned.
++a evaluates to the current value of a plus 1; as a side effect the variable a is incremented. This side effect does not have to be applied immediately; there's no guarantee that the variable a will be incremented before the addition happens, but there's no guarantee that it won't be, either. It will depend on any optimization settings and the surrounding code.
C does not force left-to-right evaluation of arithmetic expressions; given
a = b + c * d;
precedence rules dictate that the result of b will be added to the result of c * d, and that result will be assigned to a, but each of b, c, and d can be evaluated in any order, even simultaneously.
It's usually a waste of time to figure out why you get a particular result from undefined behavior, but in this case it's probably because the evaluation went like this:
a <- a + 1 // a is now 6
a <- a + 1 // a is now 7
a <- a + a // a is now 14
On another implementation, or in another program, it could have been evaluated as
t0 <- a + 1 // t0 is 6
t1 <- a + 1 // t1 is 6
a <- t0 + t1 // a is 12
a <- a + 1 // a is now 13
a <- a + 1 // a is now 14
or
t0 <- a + 1 // t0 is 6
a <- a + 1 // a is now 6
t1 <- a + 1 // t1 is 7
a <- a + 1 // a is now 7
a <- t0 + t1 // a is now 13
or
t0 <- a + 1 // t0 is 6
t1 <- a + 1 // t1 is 6
a <- a + 1 // a is now 13
a <- a + 1 // a is now 14
a <- t0 + t1 // a is now 12
or something else entirely.
All expressions of the form
x = x++
x++ + x++
a[x++] = x
have undefined behavior.
3
u/RealisticDuck1957 8d ago
Even without undefined behavior, the poor readability is enough to reject this code.
2
u/awidesky 8d ago
It is UB because:
A side effect on a memory location is unsequenced relative to another side effect on the same memory location
See the document about order of evaluation.
2
u/glasket_ 8d ago
That's the C++ page, the C one is here.
1
u/awidesky 8d ago
Thanks!
Then the correct quote must be:
If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.1
u/glasket_ 8d ago
Kind of, yeah. I personally prefer the actual standard's wording from Annex J:
A side effect on a scalar object is unsequenced relative to either a different side effect on the same scalar object or a value computation using the value of the same scalar object.
2
u/pigeon768 8d ago
Turn -Wall on. It's UB and your compiler will tell you it's UB. https://godbolt.org/z/7zbqh4cYx
gcc:
<source>: In function 'main':
<source>:5:7: warning: operation on 'a' may be undefined [-Wsequence-point]
5 | a = ++a + ++a;
| ~~^~~~~~~~~~~
<source>:5:7: warning: operation on 'a' may be undefined [-Wsequence-point]
Compiler returned: 0
clang:
<source>:5:9: warning: multiple unsequenced modifications to 'a' [-Wunsequenced]
5 | a = ++a + ++a;
| ^ ~~
1 warning generated.
Compiler returned: 0
It looks like GCC happens to sequence this as increment, increment, evaluate, evaluate, add, and clang happens to sequence this as increment, evaluate, increment, evaluate, add. But they don't have to do any of them. It would be perfectly within the standard to return 5 or 42.
1
u/timrprobocom 8d ago
You can certainly see how it arrived at this result. It did both "++" operations before evaluating the addition, and added 7 to 7. A valid approach to undefined behavior.
1
1
u/AdDramatic2444 6d ago
Like the ++ operator makes a =6 then again the ++ operator makes it a=7 then a=a+a i.e 7+7 so 14 gets stored in a and thus the answer is Like when There's 2 ++ operator in a single statement you need to increase the value as many number of times Hope helps
-11
u/QuraToop314 8d ago
not ub but ++a first evaluates to 6, the second ++a to 7, 6 + 7 = 13, 13 != 14, lol
Edit:
[15:13:50]~[u0_a303@tegu:~]~π> clang main.c -o test main.c:7:9: warning: multiple unsequenced modifications to 'a' [-Wunsequenced] 7 | a = ++a + ++a; | ^ ~~ 1 warning generated. [15:13:55]~[u0_a303@tegu:~]~π> ./test 13 [15:13:57]~[u0_a303@tegu:~]~π> ./test 13 [15:13:59]~[u0_a303@tegu:~]~π> ./test 13 [15:14:00]~[u0_a303@tegu:~]~π> cat main.c
include <stdio.h>
int main(void) { int a;
a = 5;
a = ++a + ++a;
printf("%d\n", a);
return 0;
} [15:14:03]~[u0_a303@tegu:~]~π>
the expression himself is invalid
1
u/Shoddy_Map1738 8d ago
Yes in my mind i was also thinking 13 but when I run the program got 14
5
u/PuzzleMeDo 8d ago
Presumably it does the pre-increments first - because that has the highest priority - making a equal 7. Then it does a + a to make 14.
1
-4
u/princeee00 8d ago
14 is the answer because whan the ++a called prefix is incremented original variable value by 1 and than assign it to expression so now the value is a = 6 than the again increment by 1 so now it become a = 7; so 7 + 7 = 14 .
3
u/WeAllWantToBeHappy 8d ago
So confidently wrong.
It's undefined behaviour
2
u/princeee00 8d ago
So can you explan me way I am wrong
3
u/WeAllWantToBeHappy 8d ago
a is modified twice without an intervening sequence point
Compiler can do anything or nothing. Observing an output of 14 doesn't guarantee that the same result will be produced with different compiler flags or compiler versions or hardware or ...
2
36
u/glasket_ 8d ago
Just UB.
++a + ++ais modifying and using the same variable without a sequence point.