在Linux GCC中无故出现“ Initializer元素不是常数”错误,正在编译C

在Linux GCC中无故出现“ Initializer元素不是常数”错误,正在编译C,第1张

在Linux GCC中无故出现“ Initializer元素不是常数”错误,正在编译C

C语言要求静态对象的初始化程序为常量表达式。(由于静态对象的初始化发生在

main
开始之前,所以没有地方进行任何运行时评估。)

const
尽管单词显然是相关的,但C的关键字并不表示“常量”。甲 常量表达式
是一个,可以是,在某些情况下,必须在编译时,评价。
const
表示只读。例如,在块作用域内(在函数定义内),这是:

const int r = rand();

是完全合法的。显然,初始化器无法在编译时求值;在

const
那只是意味着
r
可能没有后进行修改一直initalized。

当你写:

const unsigned long long LATITUDE = (long) 3600000;

引用

LATITUDE
不是常量表达式。编译器当然 可以
在编译时评估此类引用,但C标准不需要这样做。(必须在某个地方画出常量和非常量表达式之间的界线,该语言的作者选择使区分相对简单,很少有特殊情况。)

现在是千真万确的C语言 可以 被定义,以便

LATITUDE
为常量表达式。它是用C
++编写的,我一直主张C采用类似的规则。但是根据当前的C规则,不是这样,这意味着您不能
LATITUDE
在初始化器中使用静态对象。

这也意味着

clang
(据我所知,是
gcc
在MacOS上键入时被调用的编译器)很可能不合格,因为它无法诊断此错误。在我自己的Linux系统上,我发现
-std=c11-pedantic
gcc 4.7.2 调用时可以正确诊断错误,而clang 3.4不能。

除了 也许 从第6.6节,2011年ISO C标准的第10段(其也存在于1990和1999的标准)这个子句:

一个实现可以接受其他形式的常量表达式。

可以想象clang接受

LATITUDE
为常量表达式,因为它利用了此权限-但是我仍然希望至少收到来自的警告
clang -std=c11-pedantic -Wall -Wextra
,并且没有警告。

更新 :当我编译以下内容:

#include <stdio.h>const unsigned long long LATITUDE = (long) 3600000;int main(void) {    switch (0) {        case LATITUDE: puts("wrong"); break;        default: puts("ok(?)"); break;    }}

使用带有选项的clang 3.0

-std=c99 -pedantic
,我得到:

c.c:7:14: warning: expression is not integer constant expression (but is allowed as an extension) [-pedantic]        case LATITUDE:  ^~~~~~~~1 warning generated.

使用clang 3.4时,警告为:

c.c:7:14: warning: expression is not an integer constant expression; folding it to a constant is a GNU extension [-Wgnu-folding-constant]        case LATITUDE:  ^~~~~~~~1 warning generated.

因此clang确实认识到它不是一个常量表达式;错误是它不会警告的声明

MAX_COORDINATES_NUMBER

另一个更新

问题中的代码是:

const unsigned long long LATITUDE = (long) 3600000;const unsigned long long LonGITUDE = (long) 1810000;const unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1);

(long)
前两个声明中的强制转换没有用。常量
3600000
1810000
是(可能是)类型
int
。您将它们转换为
long
,然后使用结果初始化类型的对象
unsignedlong long
。只需删除强制类型转换;或者,如果您想更明确一些,则添加一个
ULL
后缀以使这些常量生效
unsigned long long

const unsigned long long LATITUDE = 3600000ULL;const unsigned long long LonGITUDE = 1810000ULL;

问题出在第三个声明中,该声明引用

LATITUDE
LONGITUDE
,这两个声明都不是常量表达式。不幸的是,C除了定义整数类型的命名常量之外,没有提供一种好方法
int
(您可以(将)
enum
功能用于
int
常量)。替代方法是使用宏。这有效:

#define LATITUDE 3600000ULL#define LonGITUDE 1810000ULLconst unsigned long long MAX_COORDINATES_NUMBER = (LATITUDE-1) + LATITUDE*(LONGITUDE-1);

如果您需要

MAX_COORDINATES_NUMBER
成为一个常量表达式,也可以使其成为一个宏:

#define LATITUDE 3600000ULL#define LonGITUDE 1810000ULL#define MAX_COORDINATES_NUMBER ((LATITUDE-1) + LATITUDE*(LONGITUDE-1))

MAX_COORDINATES_NUMBER
在较大的表达式中使用时,需要使用多余的括号来避免运算符优先级问题。)



欢迎分享,转载请注明来源:内存溢出

原文地址:https://www.54852.com/zaji/5019110.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-11-15
下一篇2022-11-15

发表评论

登录后才能评论

评论列表(0条)

    保存