Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Undefined behaviour in repeated use of prefix ++ operator

I read this answer about undefined behaviour, where I saw following statement:

++++++i;     // UB, parsed as (++(++(++i)))

I don't think it is undefined behaviour. I have a doubt, Is it really UB in C++? If yes, then How?

Also, I made program and compiled using g++ prog.cpp -Wall -Wextra -std=gnu++1z -pedantic command, it's working fine without any warning. It's give an expected output.

#include <iostream>
using namespace std;

int main()
{
    int i = 0;
    cout<<++++++i<<endl;
}
like image 617
msc Avatar asked Dec 01 '17 20:12

msc


2 Answers

In C++03 it is undefined behavior. In C++11 it is not. There is no sequence point between the various pre-increments. If i was a user-defined type, it would be well-defined behavior because then there would be a function call (a sequence point).

In C++11, the idea of sequence points was replaced with sequenced before/sequenced after. Defect 637 (http://www.open-std.org/jtc1/sc22/wg21/docs/cwg_defects.html#637) provides an example of a previously undefined construct becoming well-defined (i = ++i + 1).

To understand why it's not undefined behavior, let's look at the pieces we need. ++i is equivalent to i = i + 1 (except i is evaluated only once). Further if we substitute i = i + 1 with inc, ++(i = i + 1) becomes inc = inc + 1.

[expr.ass] states:

In all cases, the assignment is sequenced after the value computation of the right and left operands, and before the value computation of the assignment expression.

Thus the assignment in i = i + 1 is sequenced before value computation of inc; however, the assignment in inc = inc + 1 is sequenced after value computation of inc. There is no undefined behavior because the assignments are sequenced.

like image 171
user9041001 Avatar answered Sep 17 '22 11:09

user9041001


Sometimes behavior is undefined even though it's hard to imagine how it could be mishandled. But pre-C++11, this was undefined because the same object is modified multiple times without an intervening sequence pointed.

One could imagine a compiler that "optimized" the code by consolidating all the modifications to i. Thus each increment winds up incrementing the original value. But that's not the point. UB is UB if the standard says so. It doesn't matter whether or not we can imagine ways it can fail.

like image 33
David Schwartz Avatar answered Sep 16 '22 11:09

David Schwartz