C固定大小的数组被视为可变大小

时间:2016-06-27 12:28:22

标签: c c99

我一直在尝试定义一个大小应该在编译时知道的静态数组(它是一个常量表达式)。看来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除。我想避免动态内存分配以保持代码简单。

2 个答案:

答案 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];