在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,那么跟踪所有分配的内存块以便最终释放它们的正确方法是什么?
谢谢!
答案 0 :(得分:3)
您可以使用任何一种技术。如果在创建结构后可能需要编辑字段,则单独分配可能更合适。如果不需要编辑字段,则一次分配仅需要一次取消分配-并减少了内存碎片。每次分配都有一些开销。
如果您使用单一分配,则需要修正分配。这段代码不会检查内存分配,但是应该。
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()
,这同样是用户可定义的名称。