Sizeof operator with variable-length array type

时光怂恿深爱的人放手 提交于 2019-12-09 08:33:25

问题


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.


回答1:


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.




回答2:


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;
}



回答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




回答4:


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.



来源:https://stackoverflow.com/questions/48661057/sizeof-operator-with-variable-length-array-type

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!