+ 14

Bug in C compiler (?)

The following code prints 25. Shouldn't it be printing 20? int a = 3; printf("%d", ++a * ++a); // prints 25 I've also tested it in java compiler. It prints 20! int a = 3; System.out.print( ++a * ++a ); // prints 20 (java) Why is C compiler printing 25?? EDIT: I don't think the "operator precedence" explains this, because, in java, ++ also have higher precedence. Having a higher precedence only means that the ++ will be done first, so: 1) increment a, then use its value (use a = 4) 2) increment a again, then use its value (use a = 5) 3) multiply the results: 4 * 5 = 20 EDIT2: "All increments have to be done before the multiplication. First increment increases a to 4, then it is increased to 5. Then the multiplication takes place, and by that time, a has the value 5". Not necesseraily. If you use post-increment instead, it will not use equal values. The following code prints 12 (3*4). By the same logic, it should print 16 (4*4)... Or not, I don't know, it's very confusing >_< int a = 3; printf("%d", a++ * a++ ); // prints 12 And another thing: if all increments are done first and then the final value is used, so, the following code should print 216 (6*6*6), but it prints 150 (5*5*6) instead. int a = 3; printf("%d", ++a * ++a * ++a ); // prints 150 W H Y ?

4th Sep 2018, 5:09 AM
Lucas Jadilo
Lucas Jadilo - avatar
4 ответов
+ 5
You need a sequence point between modifications/mod+access. Oherwise the compiler can do whatever/whenever it wants, even self-inconsistently. https://en.cppreference.com/w/cpp/language/eval_order Undefined behavior: between the previous and next sequence point a scalar object must have its: 1) stored value modified at most once 2) prior value, modified by the expression's evaluation, accessed only to determine the value to store http://cpp.sh yields these warnings (code below) 6:24: warning: operation on 'a' may be undefined [-Wsequence-point] 11:25: same for 'b' 16:31: same for 'c' (twice) Disassembly (gcc 7.2.0) https://www.godbolt.org/z/Wo7UuK int a = 3; printf("%d", ++a * ++a); // prints 25 // a+=1, a+=1; ax=a; ax*=a // 5 * 5 int b = 3; printf("%d", b++ * b++ ); // prints 12 // dx=b; b+=1; ax=b; b+=1; ax*dx // 4 * 3 int c = 3; printf("%d", ++c * ++c * ++c ); // prints 150 // c+=1, c+=1; ax=c; ax*=c; c+=1; ax*=c // 5 * 5 * 6 edit/note: C and C++ sequence point locations: https://en.m.wikipedia.org/wiki/Sequence_point#Sequence_points_in_C_and_C++
8th Sep 2018, 4:43 PM
Kirk Schafer
Kirk Schafer - avatar
+ 4
First of all, you should never write a code like this in your programs. It's very confusing, so it's suitable for challenges only. As to the code. When you write b = ++a * ++a * ++a you expect the next execution plan: tmp1 = ++a; tmp2 = ++a; tmp3 = tmp1 * tmp2; tmp4 = ++a; b = tmp3 * tmp4; Java does exactly the same, and this is the case for postfix increments in C++. But not for prefix. C++ optimizes prefix increments and does not copy result to temporary variable (or register). So the plan here is: ++a; ++a; tmp1 = a * a; ++a; b = tmp1 * a; Postfix operators can not be optimized this way.
8th Sep 2018, 4:47 AM
Viacheslav
+ 4
Here's a disassembled C version of the same code (again, gcc 7.2.0 with C selected): https://godbolt.org/z/bV2gEI Though I thought they'd be identical, example 2 takes another path: int b = 3; printf("%d", b++ * b++ ); // prints 12 // dx=b (3); ax=dx+1 (4); b=ax; ax=b; cx=ax+1; b=cx; ax*dx // 4 * 3 Notes: ::: b=ax then ax=b : weird, or...something implied here? ::: I've dropped the "e" and "r" register prefixes to focus just on the bases. That abstraction is "wrong", but register acrobatics is a distraction.
8th Sep 2018, 6:09 PM
Kirk Schafer
Kirk Schafer - avatar
+ 3
Operator precedence does explain it. If you look at this: 5+8*7-2+15*3, you can't read and evaluate the expression from the left to the right. All multiplications have to be done first, then you can jump back to the beginning of the expression and solve it from the left to the right. Same in your case: all (!) increments have to be done before the multiplication. First increment increases a to 4, then it is increased to 5. Then the multiplication takes place, and by that time, a has the value 5.
4th Sep 2018, 1:33 PM
Anna
Anna - avatar