为什么不能使静态数组的大小变量?

可能重复:
我们可以给静态数组的大小一个变量

我在其中一个子文件中定义一个数组,如下所示。

static int arr[siz]; 

这里siz是子文件可用的全局变量。 但是gcc编译器会产生以下错误:

 :  : error : storage size of 'arr' isn't constant 

为什么我不能定义可变大小的static数组?

编辑:这似乎只是static int类型的问题。 如果我将arr的变量类型从static int更改为int ,则即使数组的大小仍依赖于变量siz ,错误也会消失。

由于您声明的数组的大小不是常量,因此您拥有的是可变长度数组(VLA) 。 c99标准允许VLA,但存在一些与之相关的限制。 您不能拥有带有staticextern存储类说明符的可变长度数组。

您有一个具有static存储规范的VLA,C99标准不允许这样做。

参考:

c99标准:6.7.5.2/8

示例4可变修改(VM)类型的所有声明必须处于块范围或函数原型范围。 使用static或extern存储类指定器声明的数组对象不能具有可变长度数组(VLA)类型 。 但是,使用静态存储类规范声明的对象可以具有VM类型(即指向VLA类型的指针)。 最后,所有使用VM类型声明的标识符必须是普通标识符,因此不能是结构或联合的成员。

因此,如果您需要具有static存储说明符的动态大小数组,则必须使用在堆上分配的动态数组。

 #define MAX_SIZE 256 static int* gArr; gArr = malloc(MAX_SIZE * sizeof(int)); 

编辑:
要回答您更新的问题:
从声明中删除static关键字时,声明的数组的存储说明符从static更改为全局,请注意上面的标准引用,它清楚地提到了staticextern存储规范不允许使用VLA的限制。 显然,您可以拥有具有全局存储规范的VLA,这是您删除static关键字后的内容。

您是在编译时分配数组,因此编译器必须事先知道数组的大小。 在声明arr之前,必须将siz声明为常量表达式,例如:

 #define siz 5 

要么

 enum ESizes { siz = 5 }; 

或者,如果需要在运行时确定其大小,可以使用malloc在堆上分配它:

 static int* arr; arr = (int*)malloc(siz * sizeof(int)) 

编辑 :正如eddieantonio所说,我的答案对C89有效。 在C99中,允许声明可变大小的数组。

您无法定义任何可变大小的数组。 那是因为arr[siz]使得编译器(!)为你的数组分配内存(好吧,编译器创建一个程序,那……,但不要偏离细节)。 但是,变量可以在运行时更改(!),这意味着编译器无法知道要分配多少内存。

你能做的是

 static int* arr; arr = (int*) calloc(siz,sizeof(int)) 

这些行导致程序在运行时分配内存,因此它的确切大小也可以在运行时定义。

您不能声明可变大小的static数组,因为它的空间是在数据段中分配的(如果是未初始化的变量,则为bss段 )。 因此编译器需要在编译时知道大小,并且如果大小不是常量则会抱怨。

其根本原因是数据段大小有助于生成的可执行文件的大小,这显然是在编译时创建的,因此必须修复。