0

I have been trying to digest such references as Undefined behavior and sequence points and am interested as to why the outcome of the C++ variation of the following code is different from the outcome of a C# or Javascript variation of this code (see code samples, below).

Can you elaborate on this, what I think is an anomaly in this C-family variation? I appreciate it.

EDIT: This question is about a code example that would never exist in a real-world code base. The construct is undefined in C++, and why would you ever do such a thing? As @Sebastian says,

You have two pre-increments and one addition. C++ choses (in this case with your compiler, no guarantee) to combine the two pre-increments to +2 and then sum up 7+7. That is more performant. If you want to have a defined order, use more variables or put the operations into functions. You could write i = (i + 1) + (i + 2). That ist much easier to understand for humans, too!

EDIT: This appears then to be just a mind f**k for interviewees during a job interview. Best answer: "This is undefined."

C++ Code Example ( Link: https://g.nw7us.us/3nVy02j )

// CPP program to demonstrate special
// case of post increment operator
#include <iostream>
using namespace std;
 
int main()
{
    int i = 5;
    cout << "Value of i before pre-incrementing";
    cout << "\ni = " << i;
    i = ++i + ++i;
    cout << "\nValue of i after pre-incrementing";
    cout << "\ni = " << i;
    cout << "\n+++++++++++++++++++++\n";
    i = 5;
    cout << "Value of i before pre-incrementing";
    cout << "\ni = " << i;
    i = ++i;
    cout << "\ni = " << i;
    i = i + ++i;
    cout << "\ni = " << i;
    return 0;
}

Output:

Value of i before pre-incrementing
i = 5
Value of i after pre-incrementing
i = 14
+++++++++++++++++++++
Value of i before pre-incrementing
i = 5
i = 6
i = 14

Now, here is the C# version ( link: https://g.nw7us.us/3nScCLz )

using System;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Hello World");
        
        int i = 5;
        Console.WriteLine("i = [" + i + "]");
        i = ++i + ++i;
        Console.WriteLine("i = [" + i + "]");
    }
}

Output:

Hello World
i = [5]
i = [13]

Finally, a Javascript example ( link: https://onecompiler.com/javascript/3xravf59k )

console.log("Preprocessing example...");
let i = 5;
console.log("i = [" + i + "]")
i = ++i + ++i;
console.log("i = [" + i + "]")

Output:

Preprocessing example...
i = [5]
i = [13]

I appreciate clarification on sequence points in C++, as it applies to this example.

NW7US
  • 93
  • 3
  • 10
  • 3
    Don't understand what's going on? Good, no sane reader of the code will either. Please avoid the use of such constructs in your code and if you find someone else using those, give them a kick from us. –  Jan 24 '22 at 11:53
  • Hahaha. Thanks. – NW7US Jan 24 '22 at 11:56
  • 1
    Undefined Behavior is ***UNDEFINED***. – abelenky Jan 24 '22 at 11:56
  • So, the question is really, a mind f**k, used to trip up a job interviewee. Someone asked me... and I had no valid answer. I guess my answer should be, then, "this is undefined." And that should be that. – NW7US Jan 24 '22 at 11:58
  • @abelenky since C++17 it is no longer UB. – Marek R Jan 24 '22 at 12:03
  • 1
    You have two pre-increments and one addition. C++ choses (in this case with your compiler, no guarantee) to combine the two pre-increments to `+2` and then sum up `7+7`. That is more performant. If you want to have a defined order, use more variables or put the operations into functions. You could write `i = (i + 1) + (i + 2)`. That ist much easier to understand for humans, too! – Sebastian Jan 24 '22 at 12:03
  • 1
    There are operators in C++ with defined order, e.g. the comma operator, &&, ¦¦, the ternary ? operator. But the aim is to write clear, readable code, not to win the obfuscated C contest. – Sebastian Jan 24 '22 at 12:09
  • @Sebastian - this undefined precedence answer is the most practical answer, in that it points the way to defining a defined order to the chaos. Refactoring the code would force the programmer to choose the order and code accordingly. I like clear order. – NW7US Jan 24 '22 at 12:18
  • 1
    I think some votes are about using such construct in general instead of about your question per se. Better not to take it personal ... – Sebastian Jan 24 '22 at 12:38
  • @Marek R The evaluation order of the expression `f(++i, ++i)` was specified with C++17, the expression stated in the question is still UB. Source https://en.cppreference.com/w/cpp/language/eval_order Examples in the UB paragraph. – Sebastian Jan 24 '22 at 12:45
  • 1
    The categorization as Undefined Behavior is much stronger than as Indeterminately Sequenced. – Sebastian Jan 24 '22 at 12:49

1 Answers1

4

Because (1) you never need to write cumbersome expressions like i = ++i + ++i and (2) C and C++ are all about not giving away performance, the behaviour is undefined.

(Although C++17 does define some more of these class of expressions).

On (2), different architectures may be able to optimise increments differently. That would be given away - with no real advantage gained - if the behaviour of expressions such as yours were defined.

Bathsheba
  • 231,907
  • 34
  • 361
  • 483