基于文件间const整型的结构体成员数组大小



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

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语言中是不可编译的,这使得你所说的"函数很好"的意思变得不清楚。

查看这里获得更多细节:我应该更喜欢常量而不是定义吗?

在您的情况下,您被限制为#defineenum常数。如果您还想创建指向该值的指针,则必须根据需要另外声明具有相同值的const对象,可以全局声明,也可以局部声明。但是您不能在非vla数组声明中使用它。相反,您必须使用#defineenum常量。例如

// 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文件中定义它一次。

  1. header.h

    extern const int BANANA_ARRAY_SIZE;
    
  2. 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作为数组边界。这就是它的作用

    最新更新