简体   繁体   English

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

[英]C fixed size array treated as variable size

I have been trying to define a static array with size that should be known at compile time (it's a constant expression). 我一直在尝试定义一个大小应该在编译时知道的静态数组(它是一个常量表达式)。 It appears that gcc cannot determine the size of the array when it contains a floating point constant (and I get "storage size of ... isn't constant"). 看来gcc在包含浮点常量时无法确定数组的大小(我得到“存储大小为......不是常数”)。

Here is a minimal example: 这是一个最小的例子:

int main(void)
{
    static int foo[(unsigned)(2 / 0.5)];
    return 0;
}

What is the reason for this behavior? 这种行为的原因是什么?

EDIT 编辑

I already have the answer I needed. 我已经有了我需要的答案。 I still don't understand the rationale behind not allowing that kind of expressions, but this is a separate question. 我仍然不明白不允许这种表达背后的理由,但这是一个单独的问题。 I'll explain for the curious how I arrived at the problem. 我会解释好奇我是如何解决这个问题的。

It's about a game I'm writing as an excercise. 这是一个我正在写作练习的游戏。 Units move on a battlefield and I have divided the movement in steps. 单位在战场上移动,我已逐步划分了运动。 I have to remember the position of each unit on each step so that I can display animation later. 我必须记住每个步骤中每个单元的位置,以便我以后可以显示动画。 The number of steps is chosen so that it ensures there will be a step on which units are close enough to fight each other but not so close as to collide. 选择步数,以确保有一个步骤,使得单位足够接近以相互对抗但不会碰到碰撞。 Here are the relevant pieces of code: 以下是相关的代码:

#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];

Defining DISTANCE_MELEE (maximum distance at which close combat is possible) and using it to calculate the number of steps seems to be the natural way to proceed (more so because I use this constant in multiple contexts). 定义DISTANCE_MELEE (可以进行近战的最大距离)并使用它来计算步数似乎是继续进行的自然方式(更多是因为我在多个上下文中使用此常量)。 Since I cannot define movements this way, I have to invent a concept like "number of steps for a single unit of distance" and use multiplication by int instead of division by double . 由于我无法通过这种方式定义movements ,因此我必须发明一个概念,例如“单个距离单位的步数”,并使用乘以int而不是乘以double I want to avoid dynamic memory allocation in order to keep the code simple. 我想避免动态内存分配,以保持代码简单。

According to the publicly available C99 draft standard n1256, the syntax for array declaration is described by 根据公开的C99草案标准n1256,数组声明的语法由

6.7.5.2 Array declarators 6.7.5.2数组声明符

2 2

An ordinary identifier (as defined in 6.2.3) that has a variably modified type shall have either block scope and no linkage or function prototype scope. 具有可变修改类型的普通标识符(如6.2.3中所定义)应具有块范围,无链接或函数原型范围。 If an identifier is declared to be an object with static storage duration, it shall not have a variable length array type. 如果标识符被声明为具有静态存储持续时间的对象,则它不应具有可变长度数组类型。

4 4

If the size is not present, the array type is an incomplete type. 如果大小不存在,则数组类型是不完整类型。 If the size is * instead of being an expression, the array type is a variable length array type of unspecified size, which can only be used in declarations with function prototype scope; 如果大小是*而不是表达式,则数组类型是未指定大小的可变长度数组类型,只能在具有函数原型范围的声明中使用; 124) such arrays are nonetheless complete types. 124)这样的阵列仍然是完整的类型。 If the size is an integer constant expression and the element type has a known constant size, the array type is not a variable length array type; 如果size是一个整型常量表达式,并且元素类型具有已知的常量大小,则数组类型不是可变长度数组类型; otherwise, the array type is a variable length array type. 否则,数组类型是可变长度数组类型。

So the expression in the [] must be an integer constant expression for the array to be declarable with static storage duration. 因此, []的表达式必须是可以使用static存储持续时间声明的数组的整数常量表达式 The standard has this to say about integer constant expressions: 关于整数常量表达式,标准有这个说法:

6.6 Constant expressions 6.6常量表达式

6 6

An integer constant expression 99) 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. 整数常量表达式99)应具有整数类型,并且只能具有整数常量的操作数,枚举常量,字符常量,结果为整数常量的sizeof表达式,以及作为强制转换的直接操作数的浮点常量。 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. 整数常量表达式中的转换运算符只能将算术类型转换为整数类型,除非作为sizeof运算符的操作数的一部分。

Unfortunately, (unsigned)(2 / 0.5) does not apply the cast immediately to a floating-point constant, but rather to an arithmetic constant expression . 不幸的是, (unsigned)(2 / 0.5)不会立即将强制转换应用于浮点常量,而是应用于算术常量表达式 This does not constitute an integer constant expression , and is thus not permissible as the size of an array with static storage duration. 这不构成整数常量表达式 ,因此不允许作为具有static存储持续时间的阵列的大小。

OP's primary question is well answer here . OP的主要问题是这里很好的答案。

To address OP's higher level problem of how to use values like 0.5 or 0.25 in pre-processing, use fractional arithmetic: 要解决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];

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM