📜  结构黑客

📅  最后修改于: 2021-05-25 22:00:44             🧑  作者: Mango

以下结构的大小是多少?

struct employee
{
    int     emp_id;
    int     name_len;
    char    name[0];
};

4 + 4 + 0 = 8个字节。

那“名称[0]”的大小呢?在gcc中,当我们创建长度为零的数组时,它被视为不完整类型的数组,这就是gcc将其大小报告为“ 0”字节的原因。这种技术被称为“ Stuct Hack”。当我们在结构内部创建零长度的数组时,它必须是(并且仅是)结构的最后一个成员。不久,我们将看到如何使用它。
“ Struct Hack”技术用于在结构中创建可变长度的成员。在上述结构中,“名称”的字符串长度不是固定的,因此我们可以将“名称”用作可变长度数组。

让我们看下面的内存分配。

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 */
};

注意:由于名称是字符数组,因此在malloc中而不是“ sizeof(char)* 128”中,我们可以直接使用“ 128”。 sizeof用于避免混淆。

现在,我们可以使用与指针相同的“名称”。例如

e->emp_id     = 100;
e->name_len    = strlen("Geeks For Geeks");
strncpy(e->name, "Geeks For Geeks", e->name_len);

当我们如上所述分配内存时,编译器将分配用于存储“ emp_id”和“ name_len”的内存,以及用于存储“ name”的连续内存。当我们使用这种技术时,gcc保证“名称”将获得连续的内存。
显然还有其他方法可以解决问题,一种是可以使用字符指针。但是不能保证字符指针将获得连续的内存,我们可以利用此连续的内存。例如,通过使用此技术,我们可以使用单个malloc和free调用来分配和取消分配内存(因为内存具有传染性)。这样做的另一个优点是,假设我们要写入数据,则可以使用单个“ write()”调用来写入整个数据。例如

write(fd, e, sizeof(*e) + name_len); /* write emp_id + name_len + name */ 

如果使用字符指针,则需要2个write调用来写入数据。例如

write(fd, e, sizeof(*e));         /* write emp_id + name_len */
write(fd, e->name, e->name_len);    /* write name */

注意:在C99中,有一个称为“弹性数组成员”的功能,其功能与“ Struct Hack”相同

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。