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

时间:2015-01-20 08:35:39

标签: c language-lawyer

我写了以下内容作为question关于sizeof的答案的一部分,以及它对C99 VLA的行为:

  

有意创建count_of的语义对于VLA实际上有所不同但是可能难以创建可读,易于理解/可维护的情况并不困难,和有用的案例(我没有尝试过)。

考虑到这一点后,我不确定这句话是否真的如此。要首先创建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前固定尺寸阵列?

1 个答案:

答案 0 :(得分:3)

显而易见的答案是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 ++中,这不会打印任何内容。