0

The C standard (Annex C) states that there is a sequence point

After the actions associated with each formatted input/output function conversion specifier.

Given that, why am I getting an unsequenced modification and access to i (clang) warning for the below?

int i = 0;
printf("%d, %d\n", i, ++i);

Based on the standard, there is a sequence point after the first and the second %d. If so I should be getting a 0 1? But then there is no ordering guarantee in the evaluation of function arguments and I could be getting 1 1 instead?

So what does the text of the standard I quoted really mean?

cmutex
  • 1,478
  • 11
  • 24
  • 2
    Argument evaluation order is still implementation defined. If you read e.g. [this evaluation order reference](https://en.cppreference.com/w/c/language/eval_order) you will see that it mention as example that different `%n` specifiers can write to the same variable. This is what it means, not that there are sequence points between argument evaluation. – Some programmer dude Nov 28 '19 at 20:34
  • 1
    Note too, that there are **no** *sequence points inside a string literal* between the `%d` specifiers. It is a text comma to output, and nothing else. Also please see [Undefined behavior and sequence points](https://stackoverflow.com/questions/4176328/undefined-behavior-and-sequence-points). – Weather Vane Nov 28 '19 at 20:42
  • 1
    duplicate? https://stackoverflow.com/questions/42450366/printf-the-value-of-n-in-the-same-call-senseless. It has to do with the `%n` specifier. This has defined behaviour. Not argument evaluation – Jean-François Fabre Nov 28 '19 at 20:47
  • Thanks @WeatherVane! – cmutex Nov 28 '19 at 21:17

1 Answers1

4

Given that, why am I getting an unsequenced modification and access to i (clang) warning for the below?

int i = 0;
printf("%d, %d\n", i, ++i);

Because the problem happens when evaluating the function's argument list, before the function is actually called. The evaluations of multiple arguments to the same function call are not sequenced with respect to each other, and you both read and modify i via separate, unsequenced arguments.

The provision you cited is not relevant to this issue. It describes sequence points between the I/O operations performed by the function when it executes. Because function arguments are always passed by value, and because there is a sequence point between evaluating the arguments and executing the function body, I don't see any practical relevance of that provision to the printf-family functions.

For scanf & friends, however, the provision helps ensure that

int i;
scanf("%d, %d", &i, &i);

has well-defined behavior, because it specifies that the two resulting writes to i are sequenced with respect to each other.

John Bollinger
  • 160,171
  • 8
  • 81
  • 157
  • Thanks. But when does the provision as stated in the standard apply? Can you please provide an example? I want to understand what the text of the standard I quoted means. – cmutex Nov 28 '19 at 20:42
  • It if fairly self-explanatory that the sequence point is after the I/O call [C11 Standard - 7.21.6 Formatted input/output functions](http://port70.net/~nsz/c/c11/n1570.html#7.21.6) as referenced in Annex C. – David C. Rankin Nov 28 '19 at 20:48
  • @user3124390, I have updated the answer to discuss the relevance of the provision in question. – John Bollinger Nov 28 '19 at 20:58