在结构

时间:2017-02-13 19:48:25

标签: 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的优点是

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

我的理解是,我希望检查完整性,如果你打算构建成千上万的{{​​1}}并且你确定你只需要一个动态分配的元素,那么你应该选择foo2方法,否则可读性和可扩展性的损失似乎不值得。这基本上是正确的吗?

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

1 个答案:

答案 0 :(得分:3)

  

我猜foo2方法的优点是

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

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

  

foo1的优点是

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

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

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

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

如今,大多数常见的家用台式机/笔记本电脑在处理数千件此类物品时几乎没有任何问题,每件物品的尺寸甚至高达数百KB。

永远记住,编写代码以便于维护。这很简单,可以启动你的探查器并在以后找出优化的位置(以及你是否正确优化),这样你就可以用不可读的粗略污染更少的代码,并且不太可能错过目标。

  编辑:我认为评论中的C ++旁注非常有趣,并且不介意在这一点上进行阐述 - 如果使用foo2意味着将存在不接受您的代码的C ++编译器,那么这当然是需要考虑的事情。做出决定时的帐户,对吗?

无论如何,你的代码不能用C ++编译,因为你的void示例使用时,C ++没有隐式malloc指针转换...而你确实不应该编写C风格的C ++。我们已经将死亡解释为一个社区,为什么不。我会把这些信息作为练习让你自己找。

P.S。记得释放第二次分配;)