Why is f(i = -1, i = -1) undefined behavior?

前端 未结 11 1662
再見小時候
再見小時候 2020-12-04 05:28

I was reading about order of evaluation violations, and they give an example that puzzles me.

1) If a side effect on a scalar object is un-sequenced r

11条回答
  •  抹茶落季
    2020-12-04 06:02

    First, "scalar object" means a type like a int, float, or a pointer (see What is a scalar Object in C++?).


    Second, it may seem more obvious that

    f(++i, ++i);
    

    would have undefined behavior. But

    f(i = -1, i = -1);
    

    is less obvious.

    A slightly different example:

    int i;
    f(i = 1, i = -1);
    std::cout << i << "\n";
    

    What assignment happened "last", i = 1, or i = -1? It's not defined in the standard. Really, that means i could be 5 (see harmic's answer for a completely plausible explanation for how this chould be the case). Or you program could segfault. Or reformat your hard drive.

    But now you ask: "What about my example? I used the same value (-1) for both assignments. What could possibly be unclear about that?"

    You are correct...except in the way the C++ standards committee described this.

    If a side effect on a scalar object is unsequenced relative to another side effect on the same scalar object, the behavior is undefined.

    They could have made a special exception for your special case, but they didn't. (And why should they? What use would that ever possibly have?) So, i could still be 5. Or your hard drive could be empty. Thus the answer to your question is:

    It is undefined behavior because it is not defined what the behavior is.

    (This deserves emphasis because many programmers think "undefined" means "random", or "unpredictable". It doesn't; it means not defined by the standard. The behavior could be 100% consistent, and still be undefined.)

    Could it have been defined behavior? Yes. Was it defined? No. Hence, it is "undefined".

    That said, "undefined" doesn't mean that a compiler will format your hard drive...it means that it could and it would still be a standards-compliant compiler. Realistically, I'm sure g++, Clang, and MSVC will all do what you expected. They just wouldn't "have to".


    A different question might be Why did the C++ standards committee choose to make this side-effect unsequenced?. That answer will involve history and opinions of the committee. Or What is good about having this side-effect unsequenced in C++?, which permits any justification, whether or not it was the actual reasoning of the standards committee. You could ask those questions here, or at programmers.stackexchange.com.

提交回复
热议问题