为啥允许在这里用非 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 限定变量作为数组大小?

const

为啥 const 限定变量被接受为 gcc 上的初始化程序?

const 如何做到变量在声明初始化之后不允许改变的?

C++面向对象-static、const

const