声明中的数组长度可以是非常量吗?

Can array length in declaration be non-constant?

我对 C 中的数组声明有点困惑。我知道可以这样做:

int a[20];  // Reserved space for 20 int array
int b[] = {32, 431, 10, 42};  // Length in square brackets is auto-calculated
int *c = calloc(15, sizeof(int));  // Created a pointer to the dynamic int array

但是可以这样做吗?:

int my_array[sizeof(int) * 5];

它是一个有效的代码,还是数组长度应该是一个常量表达式(在 ANSI C 中)?

(这个答案回答了标题中的问题,“声明中的数组长度可以是non-constant吗?”body中给出的例子,int my_array[sizeof(int) * 5];没有non-constant长度。)

可变长度数组在当前的 C 标准 2018 中是可选的,这意味着 C 实现可以选择支持或不支持它们。它们在 1999 年的 C 标准中是强制性的,在 2011 年的标准中是可选的。

可变长度数组只能在函数内部或参数中声明,不能在文件范围内声明,并且它们不能具有静态或线程存储持续时间。

这个声明

int my_array[sizeof(int) * 5];

没有声明变长数组,因为表达式 sizeof(int) * 5 是一个常数整数表达式。因此,即使您的编译器不支持可变长度数组,您也可以使用这样的声明。

来自 C 标准(6.6 常量表达式)

6 An integer constant expression117) shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts. Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.

和(6.7.6.2 数组声明符)

4 If the size is not present, the array type is an incomplete type. If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations or type names with function prototype scope; such arrays are nonetheless complete types. If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; otherwise, the array type is a variable length array type. (Variable length arrays are a conditional feature that implementations need not support; see 6.10.8.3.)

可变长度数组的声明可以像

const int n = 5;
int my_array[sizeof(int) * n];

可变长度数组的支持在 C11 及更高版本中是可选的。

sizeof(int) * 5 在您的问题的示例语句中使用:int my_array[sizeof(int) * 5];,是一个常量表达式,因此虽然它不能很好地说明您的主要问题,但它是合法的语法C 数组声明。

除了 C99variable length arrays 在最近的 C 编译器实现中是可选的。 (在 C99 中,必须包含 VLA。)

所以,如果你的编译器支持 VLA,下面是一个例子:

char string[100] = {0};
scanf("%99s", string);
int VLAarray1[strlen(string)+1];//per question in comments about functions to size array.
memset(VLA1array, 0, sizeof(VLAarray1));//see Note below for initialization

int arrayLen = 0;
scanf("%d", &arrayLen);
int VLAarray2[arrayLen];
memset(VLAarray2, 0, sizeof(VLAarray2));//see Note below for initialization
int nonVLAarray[100] = {0};//initialization during declaration of nonVLA

注意:VLA在其声明期间不能以任何形式初始化。与所有变量一样,最好在后续语句中通过显式为其整个内存区域赋值来初始化它。

将 VLA 作为函数参数传递不包括在您的问题范围内,但如果您对此感兴趣,good discussion on that topic here.