考虑两种定义结构的方法
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的优点是
bla->data
更容易/更快我的理解是,我希望检查完整性,如果你打算构建成千上万的{{1}}并且你确定你只需要一个动态分配的元素,那么你应该选择foo2方法,否则可读性和可扩展性的损失似乎不值得。这基本上是正确的吗?
编辑:我认为评论中的C ++旁注非常有趣,并且不介意在这一点上进行详细阐述 - 如果使用fooN
意味着将存在不接受您的代码的C ++编译器,那肯定是做出决定时需要考虑的事情,对吗?
答案 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。记得释放第二次分配;)