编译器为什么认为这个变量不是常量?

3
这是我的代码:
int main()
{
 const int LEN = 5;
 int x[LEN];
}

VS10提示:

错误 C2057:需要常量表达式

错误 C2466:无法分配大小为0的常量数组

错误 C2133:'x':未知大小

我甚至尝试了这个页面上的代码,它也出现了同样的问题(我注释了会出错的代码,并取消了正确的代码的注释):http://msdn.microsoft.com/en-us/library/eff825eh%28VS.71%29.aspx

如果我使用的是劣质编译器,我会认为这是编译器的一个bug,但它是VS2010!


3
请检查是否在其他地方对LEN进行了 #define 宏定义。 - sje397
6
@William说:#define不是定义常量的好方法,因为它们使用预处理器且缺少类型信息等;许多较新的语言甚至没有相当于#define的功能。在大多数情况下,像这样的常量是更好的实践方法。 - user541686
@Lambert:显然你不懂C语言。在C语言中,“const”变量几乎没有用处,它们肯定不能定义常量。 - R.. GitHub STOP HELPING ICE
@Lambert 好的,你的编辑让它更清晰了。谢谢。 - Michael Mrozek
1
所有的 #define 都是全局的,这就是它们为什么不好的原因。总有一天你会想在这个单元的某个地方再定义另一个 LEN。当所有的 #define 在一个 .cpp 单元中时,这并不是一个真正的大问题,但仍然可能很烦人。 - Sergei Tachenov
显示剩余5条评论
4个回答

10

你可能使用了 .c 扩展名编译代码。MS Visual C 不支持 C99。在 C89 中,数组的大小必须是常量表达式。const 限定的变量在 C 中不是真正的常量,不能在需要真正 常量 的地方使用。

还可以阅读 AndreyT 的这篇精彩文章

尝试将文件保存为 .cpp 扩展名。


在gcc中对我有效,无论我指定哪种C的方言。但是我认为你可能就调整Visual Studio方面有所发现。 - Jon Reid
1
@Jon:gcc支持C99,可变长度数组是C99的一部分,所以该代码在gcc中可以运行。该代码在C99和C++中都是有效的。 - Karthik
@Jon 使用-ansi选项,GCC会给出警告:ISO C90禁止使用可变大小的数组'x'。 - Josh Lee

2
根据http://msdn.microsoft.com/en-us/library/3ffb821x.aspx,“使用常量表达式初始化的const声明的值”在数组边界中是合法的,因此这是有效的C++代码。
因此,这要么是编译器错误,要么是某个#define引起的奇怪问题。正如sje397的评论所建议的那样,请尝试使用除LEN之外的其他名称作为长度?此外,这是否是您整个代码,还是还包括#included的头文件?
编辑添加:当然,如果将其编译为C,则这是有效的C++代码无关紧要,正如其他人所指出的。

这更像是一个未实现的功能,而不是一个严重的错误。当我将我的代码从G++移植到其他编译器时,我遇到了同样的问题,尽管我不记得是哪一个编译器了。 - Sergei Tachenov
我认为在C++中这是一个严重的错误(常量表达式应该是一个常量表达式是非常基本的),而在C99中,这个错误将是可变长度数组未实现的特性。但这是一个公正的观点。 - Brooks Moses

2

你也可以使用

int main()
{
    enum { LEN = 5 };
    int x[LEN];
}

这个可以工作。刚刚在VS2015中测试过。同时禁用了语言扩展。糟糕的是,微软在他们的文档中使用了一个不起作用的例子https://msdn.microsoft.com/en-us/library/eff825eh(VS.71).aspx。 - John Leidegren

1

因为在这种情况下,我可以做:

int main()
{
    const int LEN = 5;
    int* LENptr = (int*)(&LEN);
    *LENptr = 10;
    int x[LEN];
}

在这段代码中,const 只是表示只读,而不是编译时常量


3
这个"示例"表现出未定义行为,因此你不能从它的行为中推断任何关于语言的信息。 - CB Bailey
你可以编写那段代码,也许可以编译通过,但是去掉指针目标的const属性是否意味着可以合法地在C++中更改其值?我认为不是。如果我在该代码的末尾添加printf("%d\n", LEN);,并使用g++编译并运行它,它会打印5而不是10。我几乎惊讶它没有segfault。 - Brooks Moses
我刚刚尝试了你的代码(为了科学:),但LEN从未改变。因此,也许就像贝利所说的那样,“未定义的行为”。 - m4design
当然,我意识到原帖并没有说明这是C++还是C,我只是从C++标签中做出了假设,没有看到C标签。 - Brooks Moses
它肯定会在某些平台上出现段错误。我曾经遇到过这种情况。 - Sergei Tachenov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接