C99 VLA尺寸确定和尺寸操作员

我写了以下内容作为关于sizeof及其关于C99 VLA的行为的问题的答案的一部分:

有意识地创建一个案例,其中count_of的语义对于VLA count_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 ++中,这不会打印任何内容。