7

I just read this SO C++ FAQ about undefined behavior and sequence points and experimented a bit. In the following code gcc-4.5.2 gives me a warning only in the line mentioned in the code comment, although the one line before shows undefined behaviour too, doesn't it? You can't say which operand of addition is executed first (as + is no sequence point). Why does gcc not give me a warning in this line too?

int i=0;
int j=0;

int foo(void) {
    i=1;
    return i;
}

int main(void) {
    i = i + foo(); 
    j = j + (j=1); //Here is a rightly warning
    return 0;
}

Thank you for helping.

Community
  • 1
  • 1
halex
  • 16,253
  • 5
  • 58
  • 67
  • 2
    Consider that in many cases, `foo` might be defined in another source file, so there would be no way for the compiler to detect this. Or the access might be hidden behind a complex set of pointer dereferences. The compiler can't detect all possible cases of undefined behaviour. – Oliver Charlesworth Nov 26 '11 at 10:24
  • 3
    Also there are sequence points before the bodies of functions are entered and just before they are left as well. – Seth Carnegie Nov 26 '11 at 10:25

3 Answers3

17

The behaviour of i = i + foo(); is unspecified but not undefined. Undefined means any possible behaviour is permitted, even aborting the program. Unspecified means either i is evaluated first, or foo(). Yes, foo writes to that same i, but since it happens in a separate statement, there is a sequence point before and after that store.

  • 1
    Aborting the program would be positively benign compared with some hyper-modern compilers' treatment of Undefined Behavior. The Standard says that once a program has received input that would make Undefined Behavior inevitable, the compiler may generate the wackiest behavior imaginable without violating the standard; hyper-modern compiler philosophy encourages compilers to exploit that freedom to the utmost. – supercat Jul 01 '15 at 20:24
2

The line i = i + foo(); in your program is unspecified but not undefined.

Compilers try to emit warnings without false positives (every time the compiler warn, there is a defect that the programmer should fix), or at least with very low rates of false positives. This means that in exchange, they have quite a few false negatives. In keeping with the same philosophy, compilers usually do not warn for unspecified behaviors.

To get a warning about your program, you should look into static analyzers, which are more aggressive about warnings, at the cost of slightly more false positives. Static analyzers can very well decide to warn about unspecified behaviors. Some of them even warn about defined behaviors that, although being defined, indicate that the programmer was probably confused.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
-6

It is visible to humans that calling foo() would alter i, but for a computer programme it is hard to see. It's just not designed to see this.

bert-jan
  • 958
  • 4
  • 15