我一直在尝试定义一个大小应该在编译时知道的静态数组(它是一个常量表达式)。看来gcc在包含浮点常量时无法确定数组的大小(我得到“存储大小为......不是常数”)。
这是一个最小的例子:
int main(void)
{
static int foo[(unsigned)(2 / 0.5)];
return 0;
}
这种行为的原因是什么?
修改
我已经得到了我需要的答案。我仍然不明白不允许这种表达背后的理由,但这是一个单独的问题。 我会解释我是如何解决这个问题的好奇心。
这是关于我正在编写的一款游戏。单位在战场上移动,我已逐步划分了运动。我必须记住每个步骤中每个单元的位置,以便我以后可以显示动画。选择步数,以确保有一个步骤,使得单位足够接近以相互对抗但不会碰到碰撞。以下是相关的代码:
#define UNIT_SPEED_LIMIT 12
#define DISTANCE_MELEE 0.25
#define MOVEMENT_STEPS (unsigned)(2 * UNIT_SPEED_LIMIT / DISTANCE_MELEE)
struct position (*movements)[MOVEMENT_STEPS + 1];
定义DISTANCE_MELEE
(可以进行近战的最大距离)并使用它来计算步数似乎是自然的进行方式(更多是因为我在多个上下文中使用此常量)。由于我不能用这种方式定义movements
,我必须发明一个概念,例如“单个距离单位的步数”,并使用int
乘法而不是double
除。我想避免动态内存分配以保持代码简单。
答案 0 :(得分:5)
根据公开的C99标准草案n1256,数组声明的语法由
描述6.7.5.2数组声明符
2
具有可变修改类型的普通标识符(如6.2.3中所定义)应具有 阻止范围,没有链接或功能原型范围。如果声明了标识符 要成为具有静态存储持续时间的对象,它不应具有可变长度的数组类型。
4
如果大小不存在,则数组类型为不完整类型。如果大小是*而不是一个 表达式中,数组类型是一个可变长度数组类型 未指定的大小,只能在具有函数的声明中使用 原型范围; 124)这样的阵列仍然是完整的类型。如果 size是一个整型常量表达式,元素类型有一个 已知的常量大小,数组类型不是可变长度数组 类型;否则,数组类型是可变长度数组类型。
因此,[]
中的表达式必须是整数常量表达式,才能使用static
存储持续时间声明数组。关于整数常量表达式,标准有这个说法:
6.6常量表达式
6
整数常量表达式99)应具有整数类型且必须 只有整数常量的操作数,枚举常量, 字符常量,sizeof表达式,其结果是整数 常量和浮动常量,它们是直接操作数 管型。仅在整数常量表达式中转换运算符 将算术类型转换为整数类型,但作为一部分除外 操作数到sizeof运算符。
不幸的是,(unsigned)(2 / 0.5)
不会将 立即应用于浮点常量,而是应用于算术常量表达式。这不构成整型常量表达式,因此不允许作为具有static
存储持续时间的数组的大小。
答案 1 :(得分:1)
OP的主要问题是答案here。
要解决OP在预处理中如何使用0.5或0.25等值的更高级别问题,请使用小数算术:
#define UNIT_SPEED_LIMIT 12
// #define DISTANCE_MELEE 0.25
// use 25/100 or 1/4 or ...
#define DISTANCE_MELEE_N 1
#define DISTANCE_MELEE_D 4
// #define MOVEMENT_STEPS (unsigned)(2 * UNIT_SPEED_LIMIT / DISTANCE_MELEE)
#define MOVEMENT_STEPS (2u * UNIT_SPEED_LIMIT * DISTANCE_MELEE_D / DISTANCE_MELEE_N)
struct position (*movements)[MOVEMENT_STEPS + 1];