具有灵活数组成员的结构和具有指针成员的结构之间的区别
the difference between struct with flexible arrays members and struct with pointer members
我不再对灵活数组和指针作为结构成员之间的区别感到困惑。有人建议,struct with pointers 需要 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 struct 是否安全和能够,以及程序员在使用带指针的 struct 时 malloc 两次的确切原因是什么。
区别在于结构的存储方式。在第一个示例中,您 over-allocate 内存但这并不神奇地意味着 data
指针被设置为指向该内存。它在 malloc 之后的值实际上是不确定的,所以你不能可靠地打印它。
当然,您可以将该指针设置为指向超出结构本身分配的部分,但这意味着访问速度可能会变慢,因为您每次都需要通过指针。您还可以将指针本身分配为额外的 space (并且可能因此而额外填充),而在灵活的数组成员中 sizeof
不计算灵活的数组成员。你的第一个设计总体上比灵活的版本要麻烦得多,但除此之外 well-defined.
人们在使用带指针的结构时 malloc 两次的原因可能是他们不知道灵活的数组成员或使用 C90,或者代码不是 performance-critical 而他们只是不关心碎片化分配带来的开销
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.
如果只使用一次指针方法和malloc,在计算中需要额外注意一件事情:alignment.
让我们向结构中添加一个额外字段:
struct Vector {
size_t size;
uint32_t extra;
double *data;
};
假设我们在每个字段为 4 字节的系统上,结构上没有尾部填充且总大小为 12 字节。我们还假设 double
是 8 个字节并且需要对齐到 8 个字节。
现在有一个问题:表达式(char*)newVector + sizeof*newVector
不再给出可被8整除的地址。需要在结构和数据之间手动填充4个字节。这使得 malloc 大小计算和数据指针偏移量计算变得复杂。
所以您看到 1 个 malloc 指针版本较少的主要原因是 更难正确 。使用指针和 2 个 mallocs,或灵活的数组成员,编译器负责必要的对齐计算和填充,因此您不必这样做。
我不再对灵活数组和指针作为结构成员之间的区别感到困惑。有人建议,struct with pointers 需要 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 struct 是否安全和能够,以及程序员在使用带指针的 struct 时 malloc 两次的确切原因是什么。
区别在于结构的存储方式。在第一个示例中,您 over-allocate 内存但这并不神奇地意味着 data
指针被设置为指向该内存。它在 malloc 之后的值实际上是不确定的,所以你不能可靠地打印它。
当然,您可以将该指针设置为指向超出结构本身分配的部分,但这意味着访问速度可能会变慢,因为您每次都需要通过指针。您还可以将指针本身分配为额外的 space (并且可能因此而额外填充),而在灵活的数组成员中 sizeof
不计算灵活的数组成员。你的第一个设计总体上比灵活的版本要麻烦得多,但除此之外 well-defined.
人们在使用带指针的结构时 malloc 两次的原因可能是他们不知道灵活的数组成员或使用 C90,或者代码不是 performance-critical 而他们只是不关心碎片化分配带来的开销
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.
如果只使用一次指针方法和malloc,在计算中需要额外注意一件事情:alignment.
让我们向结构中添加一个额外字段:
struct Vector {
size_t size;
uint32_t extra;
double *data;
};
假设我们在每个字段为 4 字节的系统上,结构上没有尾部填充且总大小为 12 字节。我们还假设 double
是 8 个字节并且需要对齐到 8 个字节。
现在有一个问题:表达式(char*)newVector + sizeof*newVector
不再给出可被8整除的地址。需要在结构和数据之间手动填充4个字节。这使得 malloc 大小计算和数据指针偏移量计算变得复杂。
所以您看到 1 个 malloc 指针版本较少的主要原因是 更难正确 。使用指针和 2 个 mallocs,或灵活的数组成员,编译器负责必要的对齐计算和填充,因此您不必这样做。