所以我想在编译时已知的结构中定义数组的大小。我也希望这个数字可以作为一个变量,以便以后使用。我有以下内容:
const int BANANA_ARRAY_SIZE = 10;
typedef struct
{
char bananas[BANANA_ARRAY_SIZE];
int some_other_stuff;
} banana_struct;
这个功能很好。然而,如果我把它放在一个包含在多个地方的.h文件中,编译器就会抱怨重新定义BANANA_ARRAY_SIZE(这是有意义的)。所以我需要将它声明为一个外部变量,这样多个编译单元就可以知道它了。
现在我有了
extern const int BANANA_ARRAY_SIZE;
typedef struct
{
//.. same as before
} banana_struct;
和在实现文件中我有
const int BANANA_ARRAY_SIZE = 10;
但是现在编译器不让我定义这个结构体了抱怨
fields must have a constant size: variable length array in structure
是否有任何方法我可以实现我想要的(数组的长度存储在变量和用于定义结构体)?
编辑:对于使用#define
s的建议,我宁愿不使用。
我的问题是如何将这个常量值存储在变量中,并用于设置结构体中数组的长度。如果需要进一步说明,假设我需要一个接受指向int型的指针的函数。不能引用#define
在C语言中const
对象不是常量。您不能使用它来声明非vla数组。你的第一个声明在C语言中是不可编译的,这使得你所说的"函数很好"的意思变得不清楚。
查看这里获得更多细节:我应该更喜欢常量而不是定义吗?
在您的情况下,您被限制为#define
或enum
常数。如果您还想创建指向该值的指针,则必须根据需要另外声明具有相同值的const
对象,可以全局声明,也可以局部声明。但是您不能在非vla数组声明中使用它。相反,您必须使用#define
或enum
常量。例如
// In .h file
#define BANANA_ARRAY_SIZE 10
extern const int BANANA_ARRAY_SIZE_OBJ;
// In .c file
const int BANANA_ARRAY_SIZE_OBJ = BANANA_ARRAY_SIZE;
可以使用enum或#define
enum {
BANANA_ARRAY_SIZE = 10
};
或
#define BANANA_ARRAY_SIZE 10
您必须使用extern
,所以它不是重新定义的,您需要在单个.c
文件中定义它一次。
-
header.h
extern const int BANANA_ARRAY_SIZE;
-
c <一口> 1 一口>
void banana(void); /* provide a prototype for `banana()' */ /* A single definition */ const int BANANA_ARRAY_SIZE = 10; int main(void) { banana(); return 0; }
1 这是为了演示的目的,你不只是在现实生活中添加原型,你必须关心源代码的布局,并确保原型匹配函数定义,等等
-
banana.c
#include "header.h" #include <stdio.h> void banana(void) { printf("%dn", BANANA_ARRAY_SIZE); }
编译
gcc -Wall -Werror -o banana banana.c main.c
执行时将打印10
。
但是我建议使用宏,比如
#define BANANA_ARRAY_SIZE 10
,那么你甚至可以在编译时定义它,像这样
gcc -DBANANA_ARRAY_SIZE=10 a.c b.c d.c -o executable
以防止重定义或根本不包含公共头文件中可能包含的定义
#ifndef BANANA_ARRAY_SIZE
#define BANANA_ARRAY_SIZE 10
#endif
根据C11草案6.6#10,"实现可以接受其他形式的常量表达式".
用gcc 4.8.2试过了:
static const size_t arr_size = 10; // static does not change anything
static int arr[arr_size]; // dito
gcc -std=gnu11 -Wall test.c
test.c:6:12: error: variably modified ‘arr’ at file scope
static int arr[arr_size];
所以这不起作用(如果有的话我会很惊讶)。即使如果 id有效,它也将是实现定义的,甚至可能在同一编译器的两个补丁之间发生变化。
不工作的原因很明显,特别是如果const具有全局作用域:如果编译的模块包含带有声明的头文件,则编译器无法知道该常量变量(!)的实际值。那么它如何为.bss
节中的数组保留空间,或者能够检查初始化器的范围(并在.data
节中分配空间)?这将需要链接器的干预,并且会对初始化式等产生更大的影响。我很确定没有编译器会接受这个原因。
所以,你必须使用
#define
:
"array.h":
#define MAX_ARR_LEN 10
extern const size_t max_arr_len;
"array.c":
const size_t max_arr_len = 10;
注意:使用size_t
作为数组边界。这就是它的作用