cc11variable-length-arrayorder-of-executionc23

What is the order of evaluation of VLA dimensions?


Is the following code:

#include <stdio.h>
void case1(int array[][printf("hello ")][printf("world ")]) {}
int i = 0;
void case2(int array[][i++][i++]) {}
int main(void) {
  case1(0);
  case2(0);
  printf("%d\n", i);
}

supposed to:

Are the evaluation of VLA dimensions sizes unsequenced, indeterminably-sequenced, with some sequence? Is there a sequence point?

I tried reading https://port70.net/~nsz/c/c11/n1570.html , https://port70.net/~nsz/c/c23/n3220.pdf , https://en.cppreference.com/w/c/language/eval_order and https://en.cppreference.com/w/c/language/array but found nothing relevant.


Solution

  • Here are some relevant paragraphs from the C Standard (C23):

    6.5.2.2 Function calls

    [...]

    1. There is a sequence point after the evaluations of the function designator and the actual arguments but before the actual call. Every evaluation in the calling function (including other function calls) that is not otherwise specifically sequenced before or after the execution of the body of the called function is indeterminately sequenced with respect to the execution of the called function.

    6.8 Statements and blocks

    [...]

    Semantics

    [...]

    1. A full expression is an expression that is not part of another expression, nor part of a declarator or abstract declarator. There is also an implicit full expression in which the non-constant size expressions for a variably modified type are evaluated; within that full expression, the evaluation of different size expressions are unsequenced with respect to one another. There is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated.

    This seems to imply the following responses to your questions:

    Are the evaluation of VLA dimensions sizes unsequenced, indeterminably-sequenced, with some sequence?

    As explicitly stated in the above paragraph, the evaluation of the VLA dimensions sizes are unsequenced with respect to one another.

    Is there a sequence point?

    No there does not seem to be a sequence point, at least not according to the quoted paragraph: there is an implicit full expression in the type definition, but the VLA dimensions are just expressions within this full expression so the last phrase there is a sequence point between the evaluation of a full expression and the evaluation of the next full expression to be evaluated does not apply. There does not seem to be much space for interpretation in this context: void case2(int array[][i++][i++]) {} seems to invoke undefined behavior when the function is called, just like printf("%d\n", i++ * i++) would.

    Note however that there is a sequence point between the evaluation of printf("hello ") and printf("world ") in the call to case1(0), which makes them indeterminately sequenced rather than unsequenced.

    Is the code supposed to:

    • print world hello 2 like on gcc14.2.1 ?

    This behavior is not guaranteed but possible for the world hello part, but undefined behavior is invoked when case2 is called.

    • print hello world 2 like on clang18.1.8 ?

    Same answer: This behavior is possible for the hello world part, but undefined behavior is invoked when case2 is called.

    • be implementation defined behavior? for case1? for case2?
    • be undefined behavior? for case1? for case2?

    The language of the C Standard paragraph quoted above was the same in C17 but was less specific in previous editions of the C Standard: the phrase about the expressions defining the VLA dimensions being unsequenced was missing.