g++:数组边界不是整数常量。

9

使用这段代码,

const double rotationStep = 0.001;
const int N = 2*int(M_PI/rotationStep) + 3;

static unsigned int counts[N];

g++ 出现以下错误信息:

数组边界在 »]« 符号之前不是一个整数常量

我正在使用 g++/gcc 版本 4.6.1。

有谁能告诉我为什么 g++ 抱怨这个表达式?


请问您能否将static关键字从您的代码中删除并重新编译吗? - higuaro
@h3nr1x:这是实现定义的行为(当表达式被评估时)。 - Ed S.
没有static关键字就无法编译 - user765269
3个回答

7
截至2003年的ISO C++标准,这不是一个"整数常量表达式"。引用标准第5.19节所述:
"整数常量表达式"只能包含字面值(2.13)、枚举器、带有常量表达式初始化的整数或枚举类型的const变量或静态数据成员(8.5)、整数或枚举类型的非类型模板参数和"sizeof"表达式。浮点字面值 (2.13.3) 只能在被转换为整数或枚举类型时出现。
你可以将此更改为:
const double rotationStep = 0.001;
const int N = 2*int(M_PI/rotationStep) + 3;

转换为:

const int inverseRotationStep = 1000;
const int N = 2*int(M_PI)*inverseRotationStep + 3;

(假设M_PI已经被定义; 尽管它没有在标准中规定,但它是一种常见的扩展。)
2011年ISO C++标准稍微放宽了这个限制。5.19p3(引用N3337草案)说:

整数常量表达式是整数或非作用域枚举类型的文字常量表达式。

我认为 2*int(M_PI/rotationStep) + 3,因此N符合新规则,但你的编译器可能还没有实现它们。

4

问题在于...

g++ gives: array bound is not an integer constant before »]« token

一个const值不是常量表达式(尽管可以理解为什么会让你感到困惑)。
编辑:我最初读到这个问题时假设是C语言。问题在于此表达式没有在编译时被评估。
const int N = 2*int(M_PI/rotationStep) + 3;

虽然这可能会

const int N = 10;

正如评论中@ildjarn所指出的,浮点运算不能保证在编译时被计算。这里是我找到的相关SO帖子。


-_- 但是N在编译时被固定了 :/ 那么有没有其他解决方案来替代使用#define呢? - user765269
如果您删除static关键字,它应该可以编译而不会出现警告。 - higuaro
@EdS。您的意思是const声明中的浮点数部分是实现定义的部分,还是声明中使用了static关键字? - higuaro
@h3nr1x:浮点数部分,即表达式将被评估的时候。 - Ed S.
1
@h3nr1x:尝试使用g++ -pedantic编译。我得到了“warning: ISO C++ forbids variable length array ‘counts’ [-Wvla]”的警告。(默认情况下,g++不符合标准。) - Keith Thompson
显示剩余5条评论

1

正如Ed所指出的那样,浮点运算的优化,包括常量折叠,在编译时不能保证发生。Intel的页面对此提供了一些例子,但主要是因为舍入行为可能不同,浮点运算可能会引发异常。这篇论文更深入地探讨了这个问题(第8.3节,“算术约简”)。

GCC仅支持

“浮点表达式收缩,例如形成融合乘加操作,如果目标具有本地支持,则支持该操作”

编译器优化手册中的ffp-contract标志描述所述。


“编译时”浮点运算不能保证在“编译时”发生。这句话真的很令人困惑! :D - Ed S.

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