c - 在结构中嵌入数组

标签 c struct

考虑两种定义结构的方法

typedef struct foo1 {
    int type;
    unsigned char* data;
}

...

struct *foo1 bla = malloc(sizeof(struct foo1));
bla->data = malloc(100);

typedef struct foo2 {
    int type;
    unsigned char data[]; //note: last element, so we can malloc dynamically
}

...

struct *foo2 bla = malloc(sizeof(struct foo2) + 100);

我猜foo2方法的优点是

  • 我们节省了 sizeof(void*) 字节的内存和
  • 我们在访问 bla->data 时保存内存查找。

foo1的优点是

  • 我们可以在我们的结构中拥有任意数量的动态分配指针,而对于 foo2 我们仅限于一个(因为它必须是最后一个元素)
  • 用另一个指针覆盖bla->data更容易/更快

我的理解是,如果您计划构建数千个 fooN 并且您确定只需要一个动态分配的元素,那么您应该选择foo2 方法,否则可读性和可扩展性的损失似乎不值得。这基本上是正确的吗?

编辑:我认为评论中的 C++ 旁注非常有趣,并且不介意在这一点上进行详细说明 - 如果使用 foo2 意味着将存在不接受您的代码的 C++ 编译器,那么这肯定是您在做出决定时要考虑的因素,对吧?

最佳答案

I guess the advantages of the foo2 method is

  • we save sizeof(void*) bytes of memory and
  • we save a memory lookup when accessing bla->data.

是的,它们是一些优势。您也只有 一个 分配,这很好,因为人们往往会忘记释放 第二个。更不用说,第二次分配在幕后的存储开销可能超过 sizeof (void *) 字节。

The advantages of foo1 is

  • We can have any amount of dynamically allocated pointers in our struct, while with foo2 we are limited to one (since it has to be the last element)
  • Overwriting bla->data with another pointer is easier/faster

注意我是如何划掉第二点的吗?想一想......你用另一个指针覆盖 bla->data 的唯一原因是调整它的大小,在这种情况下你写了类似 void *temp = realloc( bla->data, new_size);.

foo2 的替代方案是什么? void *temp = realloc(bla, sizeof *bla + new_size);,是吗?这是一个更小的内存占用和一个稍微简单的表达式......我建议这可能只是更快一点,因为它对我来说似乎对缓存更友好,但是您正在使用这些分配中的一个

这个答案很复杂。如果您确实计划分配数千个元素,您应该考虑数据结构的规范化形式(即,就像您设计商业数据库一样)。当您需要调整单个 bla[n]->data 的大小时,这需要很简单,但是当您需要调整整个 bla 数组的大小时,这也需要成为一项简单的任务。这意味着 data 成员应该是 单独分配bla 分配。将您的分配保持在最低限度;在这种情况下,您只需要其中两个,并在必要时继续使用 realloc 来调整它们的大小。

当今最常见的家用台式机/笔记本电脑处理数千个此类项目几乎没有问题,即使每个项目的大小高达数百 KB。

永远记住,编写代码是为了便于维护。启动您的探查器并确定稍后要优化的位置(以及您是否正确优化)非常简单,这样您就可以减少代码中不可读的代码污染,并且不太可能错过目标。


EDIT: I thought the C++ sidenote in the comments was very interesting and would not mind elaboration on this point - if using foo2 means that there will exist C++ compilers that will not accept your code, then that is certainly something to take into account when making your decision, right?

无论如何,你的代码不会在 C++ 中编译,因为 C++ 没有你使用 malloc 的示例所需的隐式 void 指针转换......而且你真的不应该编写 C 风格的 C++。作为一个社区,我们已经向死亡解释了为什么不这样做。我会将这些信息作为练习留给您自己查找。

附言记住 free 第二个分配 ;)

关于c - 在结构中嵌入数组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42212331/

相关文章:

c - 在不引用内部结构的情况下访问另一个结构中的结构字段

在 C 中创建具有 2 个结构的单向链表

c - 使用 libconfig.h 的字符串和字符集问题

c - 我下面的代码给出了奇怪的输出。解释一下

C++ 引用参数和 C 链接

复制指针数组并打印副本

c - 静态结构初始化

c - 打印棋盘

c - 检索函数中的指针

c - C中矩阵的段错误