gcc抱怨这个:
#include <stdio.h>
static const int YY = 1024;
extern int main(int argc, char*argv[])
{
static char x[YY];
}
$ gcc -c test1.c
test1.c:在函数main':
test1.c:5: error: storage size of
中,x'不是常数
test1.c:5:错误:变量“x”的大小太大
从x的定义中删除“static”,一切都很好。
我不清楚这里发生了什么:肯定YY 是不变?
我一直认为“静态const”方法比“#define”更可取。在这种情况下有没有办法使用“静态const”?
答案 0 :(得分:14)
在C中,const变量不是“真正的”编译时常量......它实际上只是一个你不允许修改的普通变量。因此,您不能使用const int
变量来指定数组的大小。
现在,gcc有一个扩展,允许您在运行时指定数组的大小如果在堆栈上创建数组。这就是为什么当您从static
的定义中省略x
时,代码会编译。但是,这在标准C中仍然不合法。
解决方案:使用#define
。
编辑:请注意,这是C和C ++不同的一点。在C ++中,const int
是一个真正的编译时常量,可用于指定数组的大小等。
答案 1 :(得分:12)
您可以使用'enum'或'define'来声明大小:
#define XX 1024
static int const YY = 1024;
enum{ ZZ = 1024 };
extern int main(void){
static char x[XX]; // no error
*(int*)&XX = 123; // error: lvalue required as unary ‘&’ operand
static char y[YY]; // error: storage size of ‘y’ isn’t constant
*(int*)&YY = 123; // no error, the value of a const may change
static char z[ZZ]; // no error
*(int*)&ZZ = 123; // error: lvalue required as unary ‘&’ operand
}
答案 2 :(得分:1)
因为您将x声明为'static',使其成为全局变量。它只是在声明它的main()函数中才知道。通过在任何函数之外声明YY,您已将其设为全局。 'static'也使它成为一个全局的,但只有这个文件才知道。
如果您将YY声明为'const int YY = 1024',则编译器可能会将其视为#define,但具有类型。这取决于编译器。
此时有两件事可能出错。
1:
在调用main()之前,所有全局变量都在运行时初始化。
由于x和YY都是全局变量,因此它们都被初始化。
因此,全局x的运行时初始化必须根据YY中的值分配空间。如果编译器没有像使用类型的#define那样处理YY,则必须对运行时值进行编译时判断。它可能假设int的最大可能值,这实际上太大了。 (或者因为你签了它而可能是否定的。)
如果您只将YY更改为短,最好是无符号短,那么可能会感兴趣。然后它的最大值是64K。
2:
您的系统可能会限制全局空间的大小。您没有指定目标平台和操作系统,但有些只有这么多。
由于您将x声明为YY,因此您已将其设置为从全局空间中获取YY字符。其中的每个字母都基本上是全球性的。如果系统上的全局空间有限,那么它的1024个字符可能太多了。
如果将x声明为char的指针,那么它将需要sizeof(char *)个字节。 (4个字节是大多数系统上指针的大小。)有了这个,你需要将指针设置为正确的malloc空间的地址。
通过声明没有'static'的x,它变成一个局部变量,只有在执行拥有函数后才会初始化。它的空间取自堆栈,而不是全球空间。 (这对于堆栈非常有限的系统或线程来说仍然是一个问题。)YY的值早已被这一点设置,所以没有问题。
此外:
我不记得是否有任何保证全局变量以任何顺序初始化。如果没有,则可以在YY之前初始化x。如果发生这种情况,那么YY将只包含RAM的随机内容。
答案 3 :(得分:0)
接下来马丁B的回答,你可以这样做:
#include <stdio.h>
#define XSIZE 1024
static const int YY = XSIZE;
int main(int argc, char*argv[])
{
static char x[XSIZE];
}
答案 4 :(得分:0)
/* SHOULDN'T THIS WORK IN C++? */
// .h
class C {
public:
static const int kSIZE;
int a[kSIZE]; // error: array bound is not an integer constant
};
// .cc
const int C::kSIZE = 1;
/* WORKS FINE */
// .h
class C {
public:
enum eCONST { kSIZE = 1 };
int a[kSIZE];
};