C99 VLA 大小确定和 sizeof 运算符
C99 VLA size determination and sizeof operator
作为对 关于 sizeof
及其在 C99 VLA 方面的行为的回答的一部分,我写了以下内容:
It would not be difficult to intentionally create a case where the semantics of count_of
would effectively differ for a VLA but it might be difficult to create a readable, easily understandable/maintainable, and useful case (I haven't tried to).
想了想,我不确定这个说法是否属实。首先要创建 VLA,编译器必须首先确定 VLA 需要的 space 数量。
对于sizeof
,我们知道
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. (6.5.3.4/2)
虽然 VLA 大小显然是 运行 时间确定,但在对 VLA 声明符的大小表达式求值(如果有的话,包括任何副作用)之后:
The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated. (6.7.5.2/2)
所以,给定
#define count_of(arr) (sizeof(arr)/sizeof(arr[0]))
是否存在任何情况,其中宏的实际有效行为对于 VLA 与数组大小表达式为常量表达式的数组声明可能不同(即一个普通的 C99 之前的固定大小数组)?
显而易见的答案是 arr
是一个包含副作用的表达式。如果计算 sizeof
的参数,就会产生副作用。如果不评估,则没有副作用。
#include <stdio.h>
#define LENGTHOF(arr) (sizeof(arr) / sizeof(*(arr)))
void f() {
puts("f");
}
int main() {
const int n = 4;
int array[n];
return LENGTHOF(*(f(), &array)) - 4;
}
这在 C99 中有效,其中 array
是 VLA,而在 C++ 中,n
是常量表达式,而 array
不是 VLA。在 C99 中,这会打印 f
。在 C++ 中,这不会打印任何内容。
作为对 sizeof
及其在 C99 VLA 方面的行为的回答的一部分,我写了以下内容:
It would not be difficult to intentionally create a case where the semantics of
count_of
would effectively differ for a VLA but it might be difficult to create a readable, easily understandable/maintainable, and useful case (I haven't tried to).
想了想,我不确定这个说法是否属实。首先要创建 VLA,编译器必须首先确定 VLA 需要的 space 数量。
对于sizeof
,我们知道
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. (6.5.3.4/2)
虽然 VLA 大小显然是 运行 时间确定,但在对 VLA 声明符的大小表达式求值(如果有的话,包括任何副作用)之后:
The size of each instance of a variable length array type does not change during its lifetime. Where a size expression is part of the operand of a sizeof operator and changing the value of the size expression would not affect the result of the operator, it is unspecified whether or not the size expression is evaluated. (6.7.5.2/2)
所以,给定
#define count_of(arr) (sizeof(arr)/sizeof(arr[0]))
是否存在任何情况,其中宏的实际有效行为对于 VLA 与数组大小表达式为常量表达式的数组声明可能不同(即一个普通的 C99 之前的固定大小数组)?
显而易见的答案是 arr
是一个包含副作用的表达式。如果计算 sizeof
的参数,就会产生副作用。如果不评估,则没有副作用。
#include <stdio.h>
#define LENGTHOF(arr) (sizeof(arr) / sizeof(*(arr)))
void f() {
puts("f");
}
int main() {
const int n = 4;
int array[n];
return LENGTHOF(*(f(), &array)) - 4;
}
这在 C99 中有效,其中 array
是 VLA,而在 C++ 中,n
是常量表达式,而 array
不是 VLA。在 C99 中,这会打印 f
。在 C++ 中,这不会打印任何内容。