我的C程序中有以下结构
struct person {
char key[50];
char color[20];
int age;
};
我想制作一个这个结构的深层副本。我有深度复制功能设置但是我对如何深度复制字符串有点困惑。我听说有人使用strcpy
和其他人使用strdup
。
在我的程序中我想要的是,如果原始人被释放,深度复制的人的密钥和颜色不会受到影响。设置后,键和颜色不能改变。为了我的目的,我应该使用strcpy
或strdup
功能吗?
strcpy()
和strdup()
之间的区别。
strdup()
分配空格并返回指向字符串副本的指针,你还必须free()
返回指针。strcpy()
获取分配的空间并将字符串复制到其中。似乎在你的情况下它是strcpy()
,因为你的结构的字段不是指针,所以你不能为它们分配一个指向分配空间的指针,这是strdup()
返回的。
但是,正如this answer所解释的那样,你实际上并不需要。
后K&R(即标准C)你可以分配它们。下面的函数只是为了使示例清晰,您将始终只是就地分配:
void deepCopyPerson(struct person *target, struct person *src)
{
*target = *src;
}
详细说明:char数组是struct对象的一部分(真正的数组,不仅仅是指针!),因此随对象一起分配和复制。
为了满足不相信者;-)我在标准草案1570中挖掘:
6.5.16分配操作员
语义
赋值运算符将值存储在左操作数指定的对象中。 [其次是类型转换和排序注意事项,与此处无关。]
[...]
6.5.16.1简单分配
约束
以下其中一项应持有:
- [...]
- 左操作数具有与右侧类型兼容的结构或联合类型的原子,限定或非限定版本;
[...]
语义
在简单赋值(=)中,右操作数的值将转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值。
要执行包含数组(没有任何指针)的结构的深层副本,深层副本很简单
struct person x = {"Key", "Color", 42}; /* initialise to something */
struct person y = x;
如果“字符串”是指针,这不起作用。然后有必要分配新的字符串,然后使用strcpy()之类的函数来复制成员。
#include <stdlib.h>
#include <string.h>
struct pointer_person
{
char *key;
char *color;
int age;
};
struct pointer_person deep_copy(struct pointer_person p)
{
struct pointer_person retval;
retval.key = malloc(strlen(p.key) + 1);
strcpy(retval.key, p.key);
retval.color = malloc(strlen(p.color) + 1);
strcpy(retval.color, p.color);
retval.age = p->age;
return retval;
}
int main()
{
struct pointer_person p;
struct pointer_person pc;
p.key = malloc(50);
strcpy(p.key, "A key");
p.color = malloc(20);
strcpy(p.color, "A colour");
p.key = 42;
pc = deep_copy(p);
/* do stuff with pc and c */
free(p.key);
free(p.color);
free(pc.key);
free(pc.color);
return 0;
}
从上面遗漏了一些错误检查(例如,需要在复制之前检查malloc()
是否成功)。
如果你使用strcpy()
,你必须自己分配内存。 strdup()
会为你做这件事。你可以使用任何一个创建一个独立于原始的新内存块,但自然strdup()
更简单,因为它不需要单独的malloc(strlen())
调用。