13

According to cppreference:

If the type of expression is a variable-length array type, expression is evaluated and the size of the array it evaluates to is calculated at run time.

It means: if the type of expression is a VLA type, then expression is evaluated. For example:

#include <stdio.h>

int main() {
    int i = 0;
    int a[i];
    printf("%zu\n",sizeof(a[i++]));
    printf("%d\n",i); // Here, print 0 instead of 1
    return 0;
}

So, according to the reference, here i becomes 1. But, with my GCC compiler, i prints as 0.

See Wandbox Demo.

7
  • 9
    a[i++] is not an expression of a VLA type. It's ultimately a subscript expression, and has the type int. Beyond that, even for VLA's a[0] is a constraint violation. Commented Feb 7, 2018 at 10:14
  • 3
    The length of the VLA is determined at the time it is defined. In the above code, the length will be 0, so the VLA will have no elements. The size does not change after it has been defined. Also, the length needs to be greater than zero, otherwise it's undefined behavior. Commented Feb 7, 2018 at 10:18
  • 1
    @byxor - It's C++ that doesn't have them other than as compiler extensions (because said compilers also support C). Commented Feb 7, 2018 at 10:19
  • 1
    Possible duplicate of Why does sizeof(x++) not increment x? Commented Feb 7, 2018 at 10:28
  • 5
    it's about sizeof+vla, it's not a duplicate of that question Commented Feb 7, 2018 at 10:30

4 Answers 4

20

First of all, please note that an array cannot have size zero, be it a VLA or not. So your code invokes undefined behavior.

C11 6.7.6.2/5

"If the size is an expression that is not an integer constant expression:" /--/ "...each time it is evaluated it shall have a value greater than zero."


As for the actual problem, a[i++] is of type int, not of VLA type.

In order to get the side-effect, you must involve the VLA array type itself, such as sizeof(a). Only then is the operand evaluated for side effects. One example to illustrate this:

#include <stdio.h>

int main() {
    int i=1, j=1;
    int a[i][j];
    int b[1][1];

    (void) sizeof(a[--i]);
    (void) sizeof(b[--j]);
    printf("%d %d", i, j);

    return 0;
}

Here i ends up as 0 since the first sizeof is evaluated because of the VLA, but j remains 1 because --j was part of a sizeof for a regular array.

Sign up to request clarification or add additional context in comments.

4 Comments

Off topic to the original question but any idea why the standard provides a special case for the expressions of type VLA?
@Ajay Assuming int a[i];, expression sizeof a must be able to calculate correct result at runtime, because value of i is not known at compile time.
@AjayBrahmakshatriya Because the size is only set in run-time, so that it cannot necessarily get pre-calculated at compile-time.
@Lundin, it just requires value of the sizeof a[--i] to be a runtime value. There is no need to evaluate the operand. The size if inferred from the type of operand, not from its value
9

The expression in sizeof in your example is int, and not vla. If it were vla, all would work:

#include <stdio.h>

int main() {
    int i = 5;
    int a[i][i];
    printf("%zu\n",sizeof(a[--i]));
    printf("%d\n",i); // Here, print 4
    return 0;
}

Comments

3

From C Standards#6.5.3.4p2 [emphasis mine]

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

In the expression:

sizeof(a[i++])

the a[i++] is not VLA but a subscript operator expression resulting in an integer. So, the operand is not evaluated and for the same reason, compiler is giving warning on this statement:

warning: expression with side effects has no effect in an unevaluated context

Comments

3

To take the word of a clone of a normative references for it:

6.5.3.4 - The sizeof and _Alignof operators

The sizeof operator yields the size (in bytes) of its operand, which may be an expression or the parenthesized name of a type. The size is determined from the type of the operand. The result is an integer. If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant.

It would be evaluated, if you fix your example to produce an expression with VLA type, one such way

#include <stdio.h>

int main() {
    int i = 1;
    int a[5][i];
    printf("%zu\n",sizeof(a[i++]));
    printf("%d\n",i);
    return 0;
}

Prints 2 on the last line, because i is incremented.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.