具有灵活数组成员的结构体和具有指针成员的结构体之间的区别
我对灵活数组和指针作为结构成员之间的区别感到困惑。有人建议,带有指针的结构需要 malloc 两次。然而,考虑下面的代码:
struct Vector {
size_t size;
double *data;
};
int len = 20;
struct Vector* newVector = malloc(sizeof *newVector + len * sizeof*newVector->data);
printf("%p\n",newVector->data);//print 0x0
newVector->data =(double*)((char*)newVector + sizeof*newVector);
// do sth
free(newVector);
我发现一个区别是Vector的数据成员的地址没有定义。程序员需要进行转换才能“找到”准确的地址。但是,如果将 Vector 定义为:
struct Vector {
size_t size;
double data[];
};
则定义了数据的地址。
我想知道它是否安全并且能够像这样使用指针来 malloc 结构,以及程序员在使用带有指针的结构时 malloc 两次的确切原因是什么。
I'm quit confused with the difference between flexible arrays and pointer as struct members. Someone suggested, struct with pointers need malloc twice. However, consider the following code:
struct Vector {
size_t size;
double *data;
};
int len = 20;
struct Vector* newVector = malloc(sizeof *newVector + len * sizeof*newVector->data);
printf("%p\n",newVector->data);//print 0x0
newVector->data =(double*)((char*)newVector + sizeof*newVector);
// do sth
free(newVector);
I find a difference is that the address of data member of Vector is not defined. The programmer need to convert to "find" the exactly address. However, if defined Vector as:
struct Vector {
size_t size;
double data[];
};
Then the address of data is defined.
I am wondering whether it is safe and able to malloc struct with pointers like this, and what is the exactly reason programmers malloc twice when using struct with pointers.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
区别在于结构的存储方式。在第一个示例中,您分配了内存,但这并不意味着
data
指针设置为指向该内存。 Malloc之后的价值实际上是不确定的,因此您无法可靠地打印它。当然,您可以将该指针设置为超出结构本身分配的零件的指向,但这意味着由于您需要每次都需要通过指针,因此可能会较慢。另外,您将指针本身分配为额外的空间(并且可能是由于它而可能会增加填充),而在灵活的数组成员 size 中,则不计算灵活的数组成员。总体而言,您的第一个设计比灵活的版本更为麻烦,但除了定义明确的版本外。
人们两次使用指针的结构时两次Malloc可能是他们不知道灵活的数组成员或使用C90,或者是代码不是关键性的,他们只是不在乎开销由分散的分配引起。
The difference is how the struct is stored. In the first example you over-allocate memory but that doesn't magically mean that the
data
pointer gets set to point at that memory. Its value after malloc is in fact indeterminate, so you can't reliably print it.Sure, you can set that pointer to point beyond the part allocated by the struct itself, but that means potentially slower access since you need to go through the pointer each time. Also you allocate the pointer itself as extra space (and potentially extra padding because of it), whereas in a flexible array member
sizeof
doesn't count the flexible array member. Your first design is overall much more cumbersome than the flexible version, but other than that well-defined.The reason why people malloc twice when using a struct with pointers could either be that they aren't aware of flexible array members or using C90, or alternatively that the code isn't performance-critical and they just don't care about the overhead caused by fragmented allocation.
如果您只使用指针方法和malloc,则在那里,在计算中需要照顾一件额外的事情:对齐。
让我们在结构中添加一个额外的字段:
假设我们在每个字段为4个字段的系统上,结构上没有尾随填充,总尺寸为12个字节。我们还假设
double
是8个字节,需要对齐8个字节。现在存在一个问题:表达式
(char*)newVector + sizeof*newVector
不再提供8个可以分组的地址。结构和数据之间需要手动填充4个字节。这使MALLOC尺寸计算和数据指针偏移计算复杂化。因此,您看到1个Malloc指针版本的主要原因是很难正确。使用指针和2个Mallocs或灵活的数组成员,编译器会处理必要的对齐计算和填充,因此您不必这样做。
If you use pointer method and malloc only once, there is one extra thing you need to care of in the calculation: alignment.
Let's add one extra field to the structure:
Let's assume that we are on system where each field is 4 bytes, there is no trailing padding on struct and total size is 12 bytes. Let's also assume that
double
is 8 bytes and requires alignment to 8 bytes.Now there is a problem: expression
(char*)newVector + sizeof*newVector
no longer gives address that is divisible by 8. There needs to be manual padding of 4 bytes between structure and data. This complicates the malloc size calculation and data pointer offset calculation.So the main reason you see 1 malloc pointer version less, is that it is harder to get right. With pointer and 2 mallocs, or flexible array member, compiler takes care of necessary alignment calculation and padding so you don't have to.