1

Imagine that we have the code below:

int i = 1;
int j = i++ + ++i;

I know that this is a Undefined Behavior, because before the semicolon, which is a sequence point, the value of i has been changed more than once. It means that the compiler may have two possibilities even if the precedence of operator plus is Left-to-Right:

case 1)

  1. take the value of i++ --- value of i is 1
  2. take the value of ++i --- value of i is 2
  3. do the operator plus and assign the result which is 3 to j and do the side effect of i++ (the order of this step is undefined too but we don't care because it won't change the result)

case 2)

  1. take the value of i++ --- value of i is 1
  2. do the side effect of i++ --- value of i is 2
  3. take the value of ++i --- current value of i is 3
  4. do the operator plus and assign the result which is 4 to j

If nothing is wrong here, I have a question:

int j = ++i + i++;

Is the code above still an Undefined Behavior?

In my opinion, there is only one possibility:

  1. do the side effect of ++i --- value of i is 2
  2. take the value of i++ --- value of i is 2
  3. do the operator plus and assign the result which is 4 to j and do the side effect of i++ (the order of this step is undefined too but we don't care because it won't change the result)

Am I right?

Btw I've read this link:
Undefined behavior and sequence points

Community
  • 1
  • 1
Yves
  • 8,474
  • 7
  • 59
  • 114
  • 2
    There are multiple ways to evaluate your second example just as there are multiple ways to evaluate your first example – David Oct 06 '16 at 15:53
  • 2
    You've missed the Undefined Behavior concept. Anything can happen. Program can crash. Program can output 42... etc. etc. – bolov Oct 06 '16 at 15:53
  • 1
    Both are UB. And "precedence of operator" is just how to parse and put parenthesis to the expression. – Jarod42 Oct 06 '16 at 15:54
  • Case in point: [live example](http://coliru.stacked-crooked.com/a/e4a135a3194a7d37) prints 4 for clang, but if you replace `clang++` with `g++` in the command line [you get 5](http://coliru.stacked-crooked.com/a/2481655ee923d7fe). Also, both warn about UB. – mindriot Oct 06 '16 at 15:55
  • what makes you think the arguments need to be evaluated left to right? – PeterT Oct 06 '16 at 15:55
  • 2
    You're confusing both associativity and precedence with evaluation order. The parameters are evaluated in an unspecified order. Associativity only matters if there is more than one binary operator. – molbdnilo Oct 06 '16 at 15:55
  • BTW one compiler (I forgot which one) consistently evaluates operands of binary `+` right-to-left – anatolyg Oct 06 '16 at 15:56
  • Undefined behaviour is undefined. – milleniumbug Oct 06 '16 at 16:23
  • The answer you linked to says: "i = ++i + i++; // Undefined Behaviour". – GManNickG Oct 06 '16 at 16:24
  • @PeterT http://en.cppreference.com/w/cpp/language/operator_precedence – Yves Oct 06 '16 at 17:17
  • @molbdnilo Could you please use an example to explain the associativity? I don't understand. – Yves Oct 06 '16 at 17:20
  • @Thomas did I ask for precedence? I asked for [Order of evaluation](http://en.cppreference.com/w/cpp/language/eval_order) – PeterT Oct 06 '16 at 17:26
  • @meagar The linked duplicate is about C. While there is a similar topic in C as well (which is somehow interited in C++), the evolving standards of C and C++ may vary how to handle this. (I didn't check.) However, I'm not so sure that a C question is the appropriate duplicate for this C++ question. Btw. the title might need to be adjusted as well. (I stumbled into this looking for a dupl. candidate for yet another (c++) question about this.) – Scheff's Cat Sep 14 '19 at 11:13

3 Answers3

5
int j = ++i + i++;

is still undefined behavior since ++i and i++ can be processed simultaneously in multiple pipelines in some CPUs, which will lead to unpredictable results.

R Sahu
  • 196,807
  • 13
  • 136
  • 247
  • But C++ standard the precedence of operator plus is Left-to-Right. So how could `++i` and `i++` be processed simultaneously? – Yves Oct 06 '16 at 17:15
  • 2
    @Thomas. There is nothing like left-to-right precedence. There is left-to-right associativity. – R Sahu Oct 06 '16 at 17:32
  • What is "left-to-right" associativity? – Yves Oct 06 '16 at 17:40
  • 1
    @Thomas. Re. left-to-right associativity. See http://stackoverflow.com/questions/930486/what-is-associativity-of-operators-and-why-is-it-important. – R Sahu Oct 06 '16 at 21:13
  • 1
    @Thomas Operator precedence defines in which order operations on values will be done but it is undefined when an expression (such as `++i`) will be turned into a value (evaluated). This is what makes it UB. – StenSoft Feb 05 '17 at 19:01
  • @StenSoft OK. Thanks a lot. – Yves Feb 05 '17 at 19:56
3

No, you are not correct. Each of the expressions ++i and i++ modify i, so the statement modifies i more than once. That is undefined behaviour.

Note that more recent versions of the standards no longer include the concept of "sequence point".

Peter
  • 32,539
  • 3
  • 27
  • 63
  • More recent versions of the standard no longer use the **term** "sequence point", but the concept is still there. – Pete Becker Oct 06 '16 at 18:33
  • @PeteBecker: The notion of a sequence point would imply a global ordering of events--everything that happens before a sequence point precedes everything that happens after. In many cases, however, the fact that A follows B and B follows C may not necessarily imply that A follows C. For example, given `x = y & 1; z = x & 2;` a compiler would be required to compute `z` in the second statement based upon the value that will be assigned in the first statement, but if none of the variables are `volatile` it could move the write to `z` ahead of the read of `y`. – supercat Oct 06 '16 at 21:17
  • @supercat - your point being? That has always been allowed under the "as if" rule. For single-threaded programs, the change in wording was intended to make no changes from the requirements under the old wording. – Pete Becker Oct 07 '16 at 00:25
  • @PeteBecker - more recent standards certainly have the concept of sequencing (e.g. some operation may be sequenced before another, some other set of operations are unsequenced in a statement). Whether that means the concept of "sequence point" is maintained is debatable - I interpret it isn't since the term isn't there, you interpret that it is. As you say, new requirements are worded to avoid inconsistencies with older requirements. – Peter Oct 07 '16 at 11:18
-2
int i = 1;
int j = i++ + ++i;

Evaluation will happen from Right to left, i.e. firstly ++i will be processed then i++. So j will have value 4.

You will get a warning that "operation on 'i' may be undefined" but there is no problem with this expression.

Tunaki
  • 116,530
  • 39
  • 281
  • 370
AMS
  • 191
  • 1
  • 17
  • 2
    There is no problem in relying on undefined behaviour? – Tunaki Feb 05 '17 at 18:43
  • 1
    If, as you say, "C++ is not a platform independent language", then your answer is not about C++, but about C++ with compiler X on operating system Y and hardware Z. Since X, y, and Z are not specified in your answer, it seems incorrect to me. – jbapple Feb 05 '17 at 19:15
  • C++ is not platform independent language. I've seen in many codes where people have used a-lot of syntax which is undefined e.g. `int arr[4] = {11, 12, 45, 34}; int *p = arr + 1; ` In this case complier says the behaviour is undefined. But if we will deep dive in theory of C++ then it will clearly answers that which value will be returned. – AMS Feb 05 '17 at 19:20
  • Let's be practical, can you give me any example where two run for the following code will produce different outputs for the code ` int i=1; std::cout< – AMS Feb 05 '17 at 19:24
  • 1
    Yes, I can give an example. With clang++ `3.6.0-2ubuntu1~trusty1` and g++ `Ubuntu 4.8.4-2ubuntu1~14.04.3` on Ubuntu 14.04 on `Intel(R) Core(TM) i7-2600K CPU @ 3.40GHz`, the clang++-compiled program prints 4 and the g++-compiled program prints 5. – jbapple Feb 05 '17 at 20:37