为啥允许在这里用非 const 初始化静态变量?
Posted
技术标签:
【中文标题】为啥允许在这里用非 const 初始化静态变量?【英文标题】:Why it is allowed to initialize static variable with non const here?为什么允许在这里用非 const 初始化静态变量? 【发布时间】:2015-09-06 21:00:19 【问题描述】:我正在阅读this。 @Andrei T 的第一个回答说
“大”对象在 C 中永远不是常量表达式,即使 对象被声明为 const。 const 限定的对象(任何类型)是 不是 C 语言术语中的常量。它们不能用于 具有静态存储持续时间的对象的初始化器,无论 他们的类型。
例如,这不是一个常数
const int N = 5; /* `N` is not a constant in C */
上面的 N 在 C++ 中是常数,但在 C 中不是常数。 所以,如果你尝试做
static int j = N; /* ERROR */
你会得到同样的错误:试图初始化一个静态对象 有一个非常数
我同意他的回答。我还尝试了一个简单的例子,比如在 gcc 4.8.2 和 4.9.2 上,它给出了我预期的编译器错误:
#include <stdio.h>
int main(void)
const int a=5;
static int b=a;
printf("%d",b);
但是当我在ideone.com
上尝试它时,它编译并运行良好并给出了预期的结果。见现场演示here。此外,在代码块 13.12 IDE (gcc 4.7.1) 上,该程序运行良好。那么,是编译器错误还是 gcc 扩展? ideone
在后台使用什么编译器选项组合?那么,它是如何以及为什么在ideone
中编译的?是什么原因?
【问题讨论】:
我建议您接受 Grzegorz Szpetkowski 的回答。我已经提交了一份 gcc 错误报告:gcc.gnu.org/bugzilla/show_bug.cgi?id=66618 【参考方案1】:这是因为 ideone可能 使用 -O
选项调用 gcc
(优化级别 1)。即使是旧版本的 gcc
(我的是 4.4.7)也是如此:
$ gcc -ansi main.c
main.c: In function ‘main’:
main.c:6: error: initializer element is not constant
$ gcc -ansi -O main.c
$ echo $?
0
这里有趣的是,-pedantic
再次正常工作并且出现了所需的诊断消息(仅在 4.4.7 中测试,see Keith's comment):
gcc -ansi -pedantic -O main.c
main.c: In function ‘main’:
main.c:6: error: initializer element is not constant
$ echo $?
1
【讨论】:
我可以在我自己的系统上确认这种行为;-O
(或-O1
、-O2
、-O3
)导致 gcc 无法诊断错误。这是 gcc 中的一个错误。使用非常量表达式来初始化静态对象是违反约束的,需要进行诊断。该诊断可能是非致命警告,但某些诊断消息是强制性的。而且我没有看到gcc -ansi -pedantic -O main.c
(gcc 4.8.4) 的错误。
和gcc的行为不一致。它允许将a
用作static
对象的初始化程序,但不允许在case 标签中使用。【参考方案2】:
这似乎是 gcc 的专长。用-std=c89
或-pedantic
编译会报错。
由于在所有 C 标准中,这是违反约束的,因此不提供对该情况的诊断会使没有 -std=c??
选项之一的 gcc 成为不合格的编译器。
【讨论】:
提及该扩展会有所帮助。 我找不到一组导致 gcc not 报告错误的选项(版本 4.1.2 和 4.8.4)。 我搜索了GCC C-extensions list 并没有找到任何相关信息。 @hacks,他们似乎没有在您期望的地方记录这一点。实际上,由于这在 C 中是违反约束的,因此这甚至不是扩展,而是使 gcc 编译器没有指定不符合标准之一。 我已经提交了一份 gcc 错误报告:gcc.gnu.org/bugzilla/show_bug.cgi?id=66618以上是关于为啥允许在这里用非 const 初始化静态变量?的主要内容,如果未能解决你的问题,请参考以下文章
为啥允许我在 C 中使用 const 限定变量作为数组大小?