C99 VLA尺寸确定和尺寸操作员
我写了以下内容作为关于sizeof
及其关于C99 VLA的行为的问题的答案的一部分:
有意识地创建一个案例,其中
count_of
的语义对于VLAcount_of
会有所不同,但可能难以创建可读,易于理解/可维护且有用的案例(我没有尝试过)。
在考虑了这个之后,我不确定这个陈述是否真的如此。 要首先创建VLA,编译器必须首先确定VLA所需的空间量。
对于sizeof
,我们知道
如果操作数的类型是可变长度数组类型,则计算操作数; 否则,不评估操作数,结果是整数常量。 (6.5.3.4/2)
虽然VLA大小显然是运行时确定,但在评估VLA声明符的大小表达式后(如果有的话,包括任何副作用):
变长数组类型的每个实例的大小在其生命周期内不会改变。 如果size表达式是sizeof运算符的操作数的一部分,并且更改size表达式的值不会影响运算符的结果,则无法指定是否计算size表达式。 (6.7.5.2/2)
所以,给定
#define count_of(arr) (sizeof(arr)/sizeof(arr[0]))
有没有像这样的宏的实际有效行为对于VLA而不是数组大小表达式是一个常量表达式(即一个普通的C99前固定大小数组)的数组声明的情况?
显而易见的答案是当arr
是包含副作用的表达式时。 如果评估sizeof
的参数,则会发生副作用。 如果没有评估,则没有副作用。
#include #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 ++中,这不会打印任何内容。