以下结构的大小是多少?
4 + 4 + 0 = 8 个字节。
那么“name[0]”的大小呢?在 gcc 中,当我们创建一个长度为零的数组时,它被认为是不完整类型的数组,这就是 gcc 将其大小报告为“0”字节的原因。这种技术被称为“结构黑客”。当我们在结构中创建长度为零的数组时,它必须是(并且唯一的)结构的最后一个成员。很快我们将看到如何使用它。
“Struct Hack”技术用于在结构中创建可变长度成员。在上述结构中,“name”的字符串长度是不固定的,所以我们可以将“name”作为变长数组。
让我们看看下面的内存分配。
相当于
在内存分配之下
相当于
注意:由于name是字符数组,所以在malloc中不用“sizeof(char) * 128”,我们可以直接使用“128”。sizeof 用于避免混淆。
现在我们可以使用与指针相同的“名称”。例如
当我们如上所述分配内存时,编译器将分配内存来存储“emp_id”和“name_len”以及连续的内存来存储“name”。当我们使用这种技术时,gcc 保证“name”将获得连续的内存。
显然还有其他方法可以解决问题,一种是我们可以使用字符指针。但是不能保证字符指针会获得连续的内存,我们可以利用这块连续的内存。例如,通过使用这种技术,我们可以使用单个 malloc 和 free 调用来分配和释放内存(因为内存具有传染性)。这样做的另一个好处是,假设如果我们想写入数据,我们可以通过使用单个“write()”调用来写入整个数据。例如
如果我们使用字符指针,那么我们需要 2 个 write 调用来写入数据。例如
注意:在 C99 中,有一个叫做“flexible array members”的特性,它的工作原理与“Struct Hack”相同。
struct employee
{
int emp_id;
int name_len;
char name[0];
};
struct employee *e = malloc(sizeof(*e) + sizeof(char) * 128);
struct employee
{
int emp_id;
int name_len;
char name[128]; /* character array of size 128 */
};
struct employee *e = malloc(sizeof(*e) + sizeof(char) * 1024);
struct employee
{
int emp_id;
int name_len;
char name[1024]; /* character array of size 1024 */
};
e->emp_id = 100;
e->name_len = strlen("Geeks For Geeks");
strncpy(e->name, "Geeks For Geeks", e->name_len);
write(fd, e, sizeof(*e) + name_len); /* write emp_id + name_len + name */
write(fd, e, sizeof(*e)); /* write emp_id + name_len */
write(fd, e->name, e->name_len); /* write name */