C 基于文件间常量int的结构成员数组大小

C 基于文件间常量int的结构成员数组大小,c,arrays,struct,C,Arrays,Struct,所以我想在编译时定义结构中数组的大小。我也希望这个数字可以作为一个变量,以便以后使用。我所拥有的是: const int BANANA_ARRAY_SIZE = 10; typedef struct { char bananas[BANANA_ARRAY_SIZE]; int some_other_stuff; } banana_struct; 这个功能很好。然而,如果我把它放在一个包含在多个地方的.h文件中,编译器会抱怨重新定义了香蕉数组大小(这很有意义)。所以我需要将它声明为一个

所以我想在编译时定义结构中数组的大小。我也希望这个数字可以作为一个变量,以便以后使用。我所拥有的是:

const int BANANA_ARRAY_SIZE = 10;

typedef struct
{
  char bananas[BANANA_ARRAY_SIZE];
  int some_other_stuff;
} banana_struct;
这个功能很好。然而,如果我把它放在一个包含在多个地方的.h文件中,编译器会抱怨重新定义了香蕉数组大小(这很有意义)。所以我需要将它声明为一个extern,以便多个编译单元可以了解它

所以,我现在有

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。

您必须使用
extern
,因此它不会被重新定义,您需要在单个
.c
文件中定义一次

示例

  • 标题.h

  • main.c1


  • 1这是为了演示的目的,您不仅要在现实生活中添加原型,还必须关注源代码布局,并确保原型与函数定义匹配,等等

  • 香蕉

    执行时将打印
    10

    但我会推荐一个宏,比如

    #定义香蕉数组大小10
    
    然后您甚至可以在编译时定义它,如

    gcc-DBANANA\u数组大小=10a.c b.c d.c-o可执行文件
    
    为了防止重新定义或根本没有定义,公共头文件将包含

    \ifndef香蕉数组\u大小
    #定义香蕉\u数组\u大小10
    #恩迪夫
    
    您可以使用枚举或定义

    enum {
    BANANA_ARRAY_SIZE = 10
    };
    


    在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;
    
    根据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
    

    因此,这是行不通的(如果有,我会大吃一惊)。即使id有效,它也将由实现定义,甚至可能在同一编译器的两个修补程序之间发生更改

    这种方法不起作用有一个明确的原因,特别是当const具有全局作用域时:如果编译的模块包含带有声明的头,编译器就无法知道该常量变量(!)的实际值。那么它如何在
    .bss
    节中为数组保留空间,或者如果给定了初始值设定项,它如何能够检查范围(以及
    .data
    节中的alloc空间)? 这将需要链接器的干预,并且会对初始值设定者产生更大的影响,等等。我很确定没有编译器会因为给出的原因接受这一点


    因此,您必须使用
    #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\u t
    。这就是它的用途(除其他外)。

    这与OP有什么不同?他明确提到他在头文件中使用了
    extern
    。问题是在头文件中定义结构,同时在.cI中保留
    BANANA\u ARRAY\u SIZE
    定义。我知道使用extern。我甚至在我的问题中也提到了这一点。问题是“为什么我不能使用extern const值来定义数组的长度?”。另外,请参见我的编辑:使用#defines@Phildo我完全错过了这个问题,因为它看起来简单多了,但这是一个很好的问题,我还没有答案。很抱歉,gcc编译了我刚刚写的一个例子,所以无法重现您的问题,您使用的是哪个编译器,哪个版本?在C语言中,您不能用gcc按照他的要求执行操作。即使编译器会接受这一点,它充其量也只是实现定义的。显然,您只能在C中的局部范围内进行这种类型的初始化,而不能在您正在尝试的全局范围内进行初始化。在同一篇帖子中:请阅读我的最新评论,这是关于我答案的最后一条评论。在我的gcc-5.1.0中没有这种情况。
    #定义香蕉数组大小10
    char BANANA[BANANA数组大小];常量大小\u t长度=香蕉数组大小
    @Ryker:that在本地范围内也不起作用,因为VLA必须在块的顶层,而不是在结构内部(不过,有一种方法可以使用flex数组成员,但这会包含一些繁重的内容。我想知道gcc是否在这方面不符合规范,因为:const int LEN=12;char my_array[LEN];int main(){my_array[0]='a';return 0;}编译得很好…不管怎样,我猜基本上c中的“这不能根据规范来完成”。谢谢你提供的信息!@Phildo:
    -std=c99
    c11
    ?这不是“规范”“Phildo:这绝对是不符合任何版本的C。你确定你在C模式而不是C++模式编译吗?C++中的代码是合法的。@奥拉夫在我之前的注释中编译了代码->代码> GCC—STD= C11主。C o o A.OUT < /Cord>作品。
    #define BANANA_ARRAY_SIZE 10
    
    // 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;
    
    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];
    
    "array.h":
    #define MAX_ARR_LEN 10
    extern const size_t max_arr_len;
    
    "array.c":
    const size_t max_arr_len = 10;