【问题标题】:Dynamically allocate C struct and access members based on the struct memory基于结构内存动态分配 C 结构和访问成员
【发布时间】:2019-05-12 04:00:18
【问题描述】:

在 C (ANSI) 程序中,我有一个结构定义为:

typedef struct Contacts {
    char * name;
    char * email;
    char * phone;
    struct Contacts *next;
} aContact;
aContact *paContact;

根据我要存储的数据长度,是否可以将内存分配为(选项1):

paContact = (struct Contacts *) malloc(sizeof (struct Contacts) +strlen(theName) + strlen(theEmail) + strlen(thePhone) + 3);

然后执行类似(伪代码)的操作:

paContact->name = paContact;
paContact->email = paContact + strlen(name) + 1;
paContact->phone = paContact->email + strlen(email) + 1;

或者我是否必须为每个成员单独分配内存(选项 2):

paContact->name = (char*) malloc(sizeof (char)*strlen(name) + 1);
paContact->email = (char*) malloc(sizeof (char)*strlen(email) + 1);
paContact->phone = (char*) malloc(sizeof (char)*strlen(phone) + 1);

如果选项 1 不可行,那么跟踪所有分配的内存块以便最终释放它们的正确方法是什么?

谢谢!

【问题讨论】:

  • 选项 1 没问题。您可以避免内存碎片。选项2.也可以。但是您需要在释放结构之前释放 aContact 的每个字段。
  • 选项 1 要求您将指针指向 结构内存,否则您将用数据覆盖指针本身。否则它可以工作。
  • @stensal 看来你在评论中回答了。请考虑做出回答,以便将问题从未回答的问题列表中排除。

标签: c struct malloc


【解决方案1】:

您可以使用任何一种技术。如果您可能需要在创建结构后编辑字段,那么单独分配可能更合适。如果不需要编辑字段,那么单次分配只需要单次解除分配——并且还可以减少内存碎片。每次分配都有一些开销。

如果您使用单一分配,则需要修复分配。此代码不检查内存分配,但应该检查。

size_t len_name = strlen(theName);
size_t len_email = strlen(theEmail);
size_t len_phone = strlen(thePhone);
aContact *paContact = malloc(sizeof(*paContact) + len_name + len_email + len_phone + 3);

char *data = (char *)paContact + sizeof(*paContact);
paContact->name = data;
strcpy(paContact->name, theName);
data += len_name + 1;
paContact->email = data;
strcpy(paContact->email, theEmail);
data += len_email + 1;
paContact->phone = data;
strcpy(paContact->phone, thePhone);
paContact->next = NULL;

不过,使用 POSIX strdup() 可能更容易:

aContact *paContact = malloc(sizeof(*paContact));
paContact->name  = strdup(theName);
paContact->email = strdup(theEmail);
paContact->phone = strdup(thePhone);
paContact->next  = NULL;

如有必要,您可以非常轻松地为strdup() 编写代理:

char *str_dup_surrogate(const char *str)
{
    size_t len = strlen(str) + 1;
    char *result = malloc(len);
    if (result != NULL)
        memmove(result, str, len);
    return result;
}

请注意,名称 str_dup_surrogate() 避免了 C11 §7.31.13 String handling <string.h> 中指定的 C 库的未来方向。我很想将其缩短为 str_dup(),这同样是一个用户可定义的名称。

【讨论】:

  • Quib​​ble,在 size 中选择 len 可能会在替代 :) 中引起视觉上的混淆
  • 这是需要分配的内存块的长度——它适用于我。 :D 这是一个品味问题;我的多年来一直使用len 中毒。
  • 啊哈!现在我看到了。
猜你喜欢
  • 2022-11-07
  • 1970-01-01
  • 2016-07-20
  • 2021-06-04
  • 1970-01-01
  • 2021-08-25
  • 1970-01-01
  • 2021-01-25
  • 1970-01-01
相关资源
最近更新 更多