3

What is printed by the following code?

#include <stdio.h>


int f(int x) { printf("%d", x); return 1; }

int main() {
    int i = 0;
    f(i++) && f(i++);
}

Is it guaranteed to be 01, or could it be 00 with both of the post-increments happening after the statement?

Neil G
  • 32,138
  • 39
  • 156
  • 257

1 Answers1

4

As per C99 and C11, appendix C in both, there is a sequence point at the call to a function, after all the arguments have been evaluated and at the end of the first operand of the && operator.

So you're doubly protected or, as we say in Australia, if the sharks don't get you, the crocodiles will (a).

The wording is slightly different between the two iterations of the standard but they have the same effect. The C11 one is (slightly paraphrased for readability):

C11:

The following are the sequence points described earlier:

  • Between the evaluations of the function designator and actual arguments in a function call and the actual call.
  • Between the evaluations of the first and second operands of the following operators: '&&' '||' '?' ','.

The short-circuiting nature of && also means that the left hand side of the expression will be evaluated first.

So your snippet is well defined, and the output will be 01.


(a) Actually, I don't think anyone in Australia would be likely to say that, other than maybe Steve Irwin, who was gotten by neither shark nor crocodile, and would probably appreciate the irony of such.

Community
  • 1
  • 1
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • 1
    I don't believe the function calls are relevant. A function body is sequenced after the evaluation of its arguments, but the arguments themselves are not sequenced with respect to each other or any other part of the expression. `f(i++)+f(i++)` is UB. If the `i++` were inside the function, `f(&i)+f(&i)` would result in i being 2, and the sum would be 1 but the output could go either way, because the order of calls is not specified, but the calls cannot interleaved.be – rici Jan 30 '15 at 05:05
  • @rici, the intent was to show that there were _two_ sequence points between the two `i++` operations in this case, the first before calling the first function the second at the `&&`. You're correct that only one is _needed._ – paxdiablo Jan 30 '15 at 05:47
  • 6.5.2.2/10 says the the arguments and the function designator are sequenced before the function body, and that all other subexpressions in the calling expression are indeterminately sequenced with respect to the function body, but says nothing about how the evaluation of the arguments and function designator are sequenced *with respect to each other*. So the two `i++` argument evaluations are unsequenced, and consequently UB. Only if the `i++` were inside the function body (`int f(int *x){return (*x)++;}`, would the post-increments be indeterminately sequenced, as I said before. – rici Jan 30 '15 at 15:35