【问题标题】:What is the use of an array in struct with empty indices? [duplicate]结构中带有空索引的数组有什么用? [复制]
【发布时间】:2021-02-16 10:31:59
【问题描述】:

我在结构定义here 的索引中看到了一个未提及大小的数组。 然后我尝试对示例代码重复相同的操作

struct some {
char a[];
};

它会抛出一个错误:flexible array member in otherwise empty struct

所以我尝试添加另一个成员

struct some {
unsigned int x;
char a[];
};

并且编译成功;我所做的观察是sizeof(struct some) = sizeof(unsigned int)。这意味着,a 在内存中没有任何份额。

  • 什么是 C 中的灵活数组?
  • 在没有分配内存的情况下,这样的数组有什么用?
  • 它是 C 标准还是 GNU 的选项?

而且,在初始化数组时最后使用逗号, 有什么用处?

struct other array[] = {
  {....},
  {....},
};

【问题讨论】:

  • 不要在一篇文章中问无关的问题。
  • 它们对于动态分配的内存很有用,例如struct some *foo = malloc(offsetof(struct some, a[100])); 将为struct some 分配一块内存,用于存储灵活数组成员a 的100 个元素。

标签: arrays c struct linux-kernel


【解决方案1】:

什么是 C 中的灵活数组?

将空[] 的数组声明为结构的最后一个成员定义了一个灵活的数组成员。结构的基本大小不包括数组的任何空间(尽管它可能包括对齐所需的填充),但是在为整个结构分配空间时,您可以根据需要分配尽可能多的空间(使用 malloc 或相关例程)并使用数组,就好像它包含您提供的空间一样多的元素。

在没有分配内存的情况下,这样的数组有什么用?'

您有责任自己分配空间。

它是 C 标准还是 GNU 的选项?

这是标准的 C。

而且,在初始化数组时最后使用逗号, 有什么用?

允许使用宏或其他方式轻松编辑或生成初始值设定项列表很方便。

【讨论】:

    【解决方案2】:

    对于第一个问题:灵活数组对于减少内存分配很有用(而不是分配结构和缓冲区,您只分配一个结构)。

    一个例子可能会让事情更容易理解。

    让我们想象以下场景:我们有一个自定义文件格式,其中第一个 32 位整数表示大小 N,接下来的 N 字节是我们感兴趣的一些有效负载,所以:

    4 // the next 4 bytes are some data we need to parse
    1 2 3 4
    8 // the next 8 bytes represent another chunk of data
    1 2 3 5 6 7 8
    

    这可以用以下结构表示:

    struct file_chunk {
        int count;
        char *data;
    }
    

    我们不知道一个文件会有多少块,所以对于每个块我们必须进行两次分配:一个用于file_chunk 结构,另一个用于data 缓冲区:

    file_chunk *allocate_file_chunk(int Count) {
        struct file_chunk *chunk = malloc(sizeof(*chunk));
        chunk->data = malloc(Count);
        return chunk;
    }
    

    但我们知道我们总是有一个 32 位整数 N 后跟 N 字节,因此我们可以执行以下操作:

    struct file_chunk {
        int count;
        char data[]
    }
    
    file_chunk *allocate_file_chunk(int Count) {
        return malloc(sizeof(struct file_chunk) + Count * sizeof(char));
    }
    

    现在我们的结构看起来与我们从文件中读取的部分完全一样。

    该功能是在 C99 中引入的。或者,对于不支持灵活数组成员的编译器,您可能会看到使用大小为 1 的数组定义的结构:

    struct file_chunk {
        int count;
        char data[1]
    }
    

    这使得计算分配所需的大小稍微复杂一些:

    size_t file_chunk_size = sizeof(struct file_chunk) + Count * sizeof(char) - sizeof(char);
    

    至于第二个问题:你可以省略结尾的,。它只是让最后添加新条目更容易(并减少查看差异时更改的行)。

    【讨论】:

      猜你喜欢
      • 2012-09-18
      • 2020-03-28
      • 1970-01-01
      • 2012-12-15
      • 2012-06-29
      • 2016-03-31
      • 2016-12-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多