结构成员数组大小基于文件

时间:2015-06-01 20:56:55

标签: c arrays struct

所以我希望在编译时知道结构中数组大小的定义。我也希望这个号码可以作为变量使用,以方便以后使用。我所拥有的是以下内容:

const int BANANA_ARRAY_SIZE = 10;

typedef struct
{
  char bananas[BANANA_ARRAY_SIZE];
  int some_other_stuff;
} banana_struct;

这个功能很好。但是,如果我将它放在一个包含在多个位置的.h文件中,编译器会抱怨重新定义BANANA_ARRAY_SIZE(这是有道理的)。所以我需要将它声明为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

有什么方法可以实现我想要的(将数组的长度存储在变量中并用于定义struct)?

修改

在回应使用#define s的建议时,我宁愿不这样做。

我的问题是关于如何将此常量值存储在变量中,还用于设置结构中数组的长度。如果你需要进一步的理由,假设我需要一个带有指向int的指针的函数。无法参考#define。

4 个答案:

答案 0 :(得分:7)

在C语言中==对象不是常量。您不能使用它来声明非VLA数组。您的第一个声明不能用C语言编写,这使得“函数正常”的含义不清楚。

请点击此处了解详情:Shall I prefer constants over defines?

在您的情况下,您只能使用const#define常量。如果您还想创建指向该值的指针,则还必须根据需要在全局或本地声明具有相同值的enum对象。但是你将无法在非VLA数组声明中使用它。相反,您必须使用const#define常量。 E.g。

enum

答案 1 :(得分:4)

您可以使用枚举或{ 'comment': 'Functions' 'match': '^\\s*(function)\\s*(\\w*)' 'captures': '1': 'name': 'variable.other.newlang' '2': 'name': 'support.function.any-method.newlang' }

#define

enum {
BANANA_ARRAY_SIZE = 10
};

答案 2 :(得分:0)

您必须使用/,因此它不是 redifined ,您需要在一个extern文件中定义一次。

示例

  1. header.h

    .c
  2. main.c中 1

    extern const int BANANA_ARRAY_SIZE;
    
  3. 1 这是出于演示目的,您不必在现实生活中添加原型,您必须关心源代码布局并确保原型与函数匹配定义等

    1. banana.c

      void banana(void); /* provide a prototype for `banana()' */
      /* A single definition */
      const int BANANA_ARRAY_SIZE = 10;
      
      int main(void)
       {
          banana();
          return 0;
       }
      
    2. 使用。编译

      #include "header.h"
      #include <stdio.h>
      
      void banana(void)
       {
          printf("%d\n", 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
      

答案 3 :(得分:0)

根据C11草案6.6#10,&#34;实现可以接受其他形式的常量表达。&#34;。

尝试使用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。这就是它(以及其他)的用途。