GCC 不支持简单的整数常量表达式?
GCC doesn't support simple integer constant expression?
GCC 4.9 和 5.1 reject 这个简单的 C99 全局范围声明。 Clang 接受它。
const int a = 1, b = a; // error: initializer element is not constant
这么基本的功能怎么能少呢?看起来很直接。
因为 const
不构成常量表达式——它构成一个无法赋值(只能初始化)的变量。你需要 constexpr
来做一个常量表达式,它只在 C++ 中可用。 C99 无法制作命名常量表达式(除了宏,它有点像,但根本不是真正的表达式)。
This is just the rules of C。一直都是这样。在文件范围内,初始化器必须是常量表达式。常量表达式的定义不包括用 const
限定符声明的变量。
要求初始化程序在编译时可计算的基本原理是,编译器可以将所有初始化的静态数据作为一个块放入可执行文件中,然后在加载时将该块作为一个块加载到内存中whole 瞧,全局变量都有正确的初始值,无需执行任何代码。
事实上,如果您可以将可执行代码作为全局变量的初始值设定项,它会引入相当多的关于代码应该 运行 的顺序的复杂性。(这在现代 C++ 中仍然是一个问题) .
在K&R C中,没有const
。他们可能有一个规则,如果一个全局变量被一个常量表达式初始化,那么这个变量也算作一个常量表达式。当 C89 中添加 const
时,他们 可能 还添加了一条规则,即 const int a = 5;
导致常量表达式。
然而他们没有。我不知道为什么肯定,但它似乎与保持语言简单有关。考虑一下:
extern const int a, b = a;
const int a = 5;
在另一个单位。无论您是否允许这样做,对于编译器来说都是相当复杂的,并且是一些更随意的决定。
如果您查看常量表达式的当前 C++ 规则(这些规则仍然没有让每个人都满意!),您会发现每次添加对一个 "obvious" 事物的支持时,就会有两个其他 "obvious" 排在后面的东西,它是永无止境的。
在 C 的早期,在 1970 年代,保持编译器的简单性很重要,所以让编译器支持这可能意味着编译器使用了太多的系统资源,或者其他什么。 (希望那个时代的coder能多多指教!)
最后,C89 标准化是一个颇具争议的过程,因为有许多不同的 C 编译器,每个编译器都在语言演化过程中走自己的路。要求不支持此功能的编译器供应商更改其编译器以支持此功能可能会遭到反对,从而降低标准的采用率。
C991节6.6 Constant expressions
是控制节。它在 6
和 7
小节中说明:
6/ An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.
Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.
整数和浮点常量的定义在标准的 6.4.4
中指定,并且仅限于实际的 值 (文字)而不是变量。
7/ More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following (a) an arithmetic constant expression, (b) a null pointer constant, (c) an address constant, or (d) an address constant for an object type plus or minus an integer constant expression.
由于 a
是 none 小节 6
或 7
中的那些内容,因此不被视为符合标准的常量表达式。
因此,真正的问题不是为什么 gcc
拒绝它,而是为什么 clang
接受它,而且这似乎隐藏在同一部分的 10
小节中:
10/ An implementation may accept other forms of constant expressions.
换句话说,标准规定了实现 必须 允许常量表达式但不限制实现只允许 .
1 除了允许 _Alignof
和 sizeof
.
等小事情外,C11 几乎相同
GCC 4.9 和 5.1 reject 这个简单的 C99 全局范围声明。 Clang 接受它。
const int a = 1, b = a; // error: initializer element is not constant
这么基本的功能怎么能少呢?看起来很直接。
因为 const
不构成常量表达式——它构成一个无法赋值(只能初始化)的变量。你需要 constexpr
来做一个常量表达式,它只在 C++ 中可用。 C99 无法制作命名常量表达式(除了宏,它有点像,但根本不是真正的表达式)。
This is just the rules of C。一直都是这样。在文件范围内,初始化器必须是常量表达式。常量表达式的定义不包括用 const
限定符声明的变量。
要求初始化程序在编译时可计算的基本原理是,编译器可以将所有初始化的静态数据作为一个块放入可执行文件中,然后在加载时将该块作为一个块加载到内存中whole 瞧,全局变量都有正确的初始值,无需执行任何代码。
事实上,如果您可以将可执行代码作为全局变量的初始值设定项,它会引入相当多的关于代码应该 运行 的顺序的复杂性。(这在现代 C++ 中仍然是一个问题) .
在K&R C中,没有const
。他们可能有一个规则,如果一个全局变量被一个常量表达式初始化,那么这个变量也算作一个常量表达式。当 C89 中添加 const
时,他们 可能 还添加了一条规则,即 const int a = 5;
导致常量表达式。
然而他们没有。我不知道为什么肯定,但它似乎与保持语言简单有关。考虑一下:
extern const int a, b = a;
const int a = 5;
在另一个单位。无论您是否允许这样做,对于编译器来说都是相当复杂的,并且是一些更随意的决定。
如果您查看常量表达式的当前 C++ 规则(这些规则仍然没有让每个人都满意!),您会发现每次添加对一个 "obvious" 事物的支持时,就会有两个其他 "obvious" 排在后面的东西,它是永无止境的。
在 C 的早期,在 1970 年代,保持编译器的简单性很重要,所以让编译器支持这可能意味着编译器使用了太多的系统资源,或者其他什么。 (希望那个时代的coder能多多指教!)
最后,C89 标准化是一个颇具争议的过程,因为有许多不同的 C 编译器,每个编译器都在语言演化过程中走自己的路。要求不支持此功能的编译器供应商更改其编译器以支持此功能可能会遭到反对,从而降低标准的采用率。
C991节6.6 Constant expressions
是控制节。它在 6
和 7
小节中说明:
6/ An integer constant expression shall have integer type and shall only have operands that are integer constants, enumeration constants, character constants, sizeof expressions whose results are integer constants, and floating constants that are the immediate operands of casts.
Cast operators in an integer constant expression shall only convert arithmetic types to integer types, except as part of an operand to the sizeof operator.
整数和浮点常量的定义在标准的 6.4.4
中指定,并且仅限于实际的 值 (文字)而不是变量。
7/ More latitude is permitted for constant expressions in initializers. Such a constant expression shall be, or evaluate to, one of the following (a) an arithmetic constant expression, (b) a null pointer constant, (c) an address constant, or (d) an address constant for an object type plus or minus an integer constant expression.
由于 a
是 none 小节 6
或 7
中的那些内容,因此不被视为符合标准的常量表达式。
因此,真正的问题不是为什么 gcc
拒绝它,而是为什么 clang
接受它,而且这似乎隐藏在同一部分的 10
小节中:
10/ An implementation may accept other forms of constant expressions.
换句话说,标准规定了实现 必须 允许常量表达式但不限制实现只允许 .
1 除了允许 _Alignof
和 sizeof
.