我在其中一个子文件中定义了一个数组,如下所示。
static int arr[siz];
此处siz
是子文件可用的全局变量。但是gcc编译器会产生以下错误:
<filename>: <line_num> : error : storage size of ‘arr’ isn’t constant
为什么我不能定义可变大小的static
数组?
编辑:这似乎只是static int
类型的问题。如果我将arr
的变量类型从static int
更改为int
,则错误消失,即使数组的大小仍依赖于变量siz
。
答案 0 :(得分:14)
由于您声明的数组大小不是常量,因此您拥有的是可变长度数组(VLA)。 c99标准允许VLA,但存在一些与之相关的限制。您不能拥有带static
或extern
存储类说明符的可变长度数组。
您的VLA具有static
存储规范,C99标准不允许这样做。
参考:
c99标准:6.7.5.2/8
示例4可变修改(VM)类型的所有声明必须处于块范围或 功能原型范围。 使用静态或外部存储类指定器声明的数组对象不能具有可变长度数组(VLA)类型。但是,使用静态存储类指定器声明的对象可以具有VM类型(即指向VLA类型的指针)。最后,所有使用VM类型声明的标识符必须是普通标识符,因此不能成为结构或联合的成员。
因此,如果您需要具有static
存储说明符的动态大小数组,则必须使用在堆上分配的动态数组。
#define MAX_SIZE 256
static int* gArr;
gArr = malloc(MAX_SIZE * sizeof(int));
修改强>
回答您的最新问题:
从声明中删除static
关键字时,声明的数组的存储说明符从static
更改为全局,请注意上面的标准引用,它明确提到了{{{{{{ 1}}和static
存储规范。显然,您可以拥有具有全局存储规范的VLA,这是您删除extern
关键字后的内容。
答案 1 :(得分:3)
您正在编译时分配数组,因此编译器必须事先知道数组的大小。在声明siz
之前,您必须将arr
声明为常量表达式,例如:
#define siz 5
或
enum ESizes
{
siz = 5
};
或者,如果您需要在运行时确定其大小,可以使用malloc
在堆上分配它:
static int* arr;
arr = (int*)malloc(siz * sizeof(int))
编辑:正如eddieantonio所说,我的答案对C89有效。在C99中,允许声明可变大小的数组。
答案 2 :(得分:1)
您无法定义任何可变大小的数组。那是因为arr[siz]
使得编译器(!)为你的数组分配内存(好吧,编译器创建一个程序,那......,但不要偏离细节)。但是,变量可以在运行时更改(!),这意味着编译器无法知道要分配多少内存。
你能做的是
static int* arr;
arr = (int*) calloc(siz,sizeof(int))
这些行导致程序在运行时分配内存,因此它的确切大小也可以在运行时定义。
答案 3 :(得分:0)
您无法声明可变大小的static
数组,因为其空间在Data Segment(或bss segment中分配,如果是未初始化的变量)。因此编译器需要在编译时知道大小,并且如果大小不是常数则会抱怨。
这个的根本原因是数据段大小有助于生成的可执行文件的大小,这显然是在编译时创建的,因此必须修复。