1

In an expression of the form

f( g(), h() );

the evaluation order of g() and h() is not defined. It is only specify that one must happen before the other. If g() and h() both have visible side effects upon which program execution depends, is this undefined behavior?

Ralph Tandetzky
  • 22,780
  • 11
  • 73
  • 120
  • http://stackoverflow.com/a/621548/276949 - it would be defined for a particular compiler, but non-portable. – Martin Konecny Jan 02 '16 at 19:18
  • 3
    Not undefined behavior upfront... but the evaluation may be this way in one evaluation, and the next time another order. If there is UB for a particular order, then however the program as a whole has UB, independent of whether your implementation ever has that particular order. – Johannes Schaub - litb Jan 02 '16 at 19:20
  • It's not UB, but it doesn't matter what you call it - your program is broken either way! – Oliver Charlesworth Jan 02 '16 at 19:22
  • 2
    Example: `int x = 1; int f() { return 1 / x; } int g(int,int) { return --x; } int main() { g(g(0, 0), f()); }`. This program has undefined behavior, even though your particular implementation may never actually evaluate `g(0,0)` before `f()`. – Johannes Schaub - litb Jan 02 '16 at 19:25

2 Answers2

6

"Undefined behavior" has a very specific technical meaning: it means that there are literally no restrictions whatsoever on what the program can do. It could set the computer on fire or insult the user. Here, the execution order is unspecified - there are a couple of options of what could happen depending on the order in which things are evaluated. You just can't predict precisely which one it's going to be without knowing more about the compiler, the optimizer, and the execution environment.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
  • 1
    ... But as long as none of those orders result in UB, all is peachy. – Deduplicator Jan 02 '16 at 19:28
  • @Deduplicator Yes, definitely. People write code like the above code all the time, and as long as the functions don't do Cruel and Unusual Things to global state, there aren't any problems. – templatetypedef Jan 02 '16 at 19:29
  • @Deduplicator - But not if the functions "both have visible side effects upon which program execution depends" - then your program will randomly break, regardless of UB. – Oliver Charlesworth Jan 02 '16 at 19:30
  • 1
    @OliverCharlesworth Not if both function's side effects can take place without the other. If `g()` writes to a file `g`, `h()` writes to a file `h`, and `f(g(), h())` reads files `g` and `h`, it doesn't matter which file was written to first, but it does matter that both functions' side effects take place before `f` starts. –  Jan 02 '16 at 19:34
  • 1
    In "The C++ Programming Language" Stroustrup wrties on page 260: "Order dependence of argument expressions is very poor style and has undefined behavior." - so is he wrong? – marcinj Jan 02 '16 at 19:35
  • @hvd - Combined with the question title ("program execution depends on execution order"), I'd wager that the OP is thinking of more pernicious examples where the order of the side-effects is relevant. – Oliver Charlesworth Jan 02 '16 at 19:36
  • @OliverCharlesworth If your interpretation of the question is right, then yeah, I agree with you. I don't read the question the same way, but I can definitely see why you do read it like that. –  Jan 02 '16 at 19:38
  • @luksan: Stroustrup's book was written before the terms "undefined behavior" and "unspecified behaivor" had well-defined (in the spec sense) and distinct meanings... – Chris Dodd Jan 02 '16 at 19:39
  • 2
    @luskan I would think that "depending on" something means that if it doesn't hold, things break badly (in other words, undefined behavior). What the OP is about is merely whether visible side-effects could change. If you don't care about their order, then you don't depend on them (IMO). – Johannes Schaub - litb Jan 02 '16 at 19:41
2

No it's not. The term undefined behavior means that anything can happen (including crashes) in the program. Here the behavior is unpredictable, meaning that one thing might happen or the other, and you cannot rely on the order of evaluation.

The big difference is that in your case, theorically you could get back on track in your program by testing which order was chosen after each call, and acting accordingly. On the other hand, once you've hit a undefined behavior case, you're screwed: it can bite you anytime, anywhere, in any way, until the program ends.

Ilya
  • 5,377
  • 2
  • 18
  • 33