简体   繁体   English

在C中使用char数组深度复制结构(如何复制数组?)

[英]Deep copying structs with char arrays in C (How to copy the arrays?)

I have the following struct in my C program 我的C程序中有以下结构

struct person {
    char key[50];
    char color[20];
    int age;
};

I want to make a deep copy of this struct. 我想制作一个这个结构的深层副本。 I've got my deep copy function setup however I'm a bit confused about how to deep copy strings. 我有深度复制功能设置但是我对如何深度复制字符串有点困惑。 I've heard of people using strcpy and others using strdup . 我听说有人使用strcpy而其他人使用strdup

What I want in my program is for the deep copied person's key and color not to be affected if the original person is freed. 在我的程序中我想要的是,如果原始人被释放,深度复制的人的密钥和颜色不会受到影响。 Once set, the key and color cannot change. 设置后,键和颜色不能改变。 For my purpose, should I be using the strcpy or strdup function? 为了我的目的,我应该使用strcpy还是strdup函数?

Post-K&R (ie in standard C) you can just assign them. 后K&R(即标准C)你可以分配它们。 The function below is just to make the example clear, you would always just assign in-place: 下面的函数只是为了使示例清晰,您将始终只是就地分配:

void deepCopyPerson(struct person *target, struct person *src)
{
    *target = *src;
}

To elaborate: The char arrays are part of your struct object (true arrays, not only pointers!), and as such are allocated and copied with the object. 详细说明:char数组是struct对象的一部分(真正的数组,不仅仅是指针!),因此随对象一起分配和复制。

In order to satisfy the disbeliefers ;-) I dug around in the standard draft 1570 : 为了满足不相信者;-)我在标准草案1570中挖掘:

6.5.16 Assignment operators 6.5.16分配操作员

Semantics 语义

An assignment operator stores a value in the object designated by the left operand. 赋值运算符将值存储在左操作数指定的对象中。 [Followed by type conversion and sequencing considerations which are not relevant here.] [其次是类型转换和排序注意事项,与此处无关。]

[...] [...]

6.5.16.1 Simple assignment 6.5.16.1简单分配

Constraints 约束

One of the following shall hold: 以下其中一项应持有:

  • [...] [...]

  • the left operand has an atomic, qualified, or unqualified version of a structure or union type compatible with the type of the right; 左操作数具有与右侧类型兼容的结构或联合类型的原子,限定或非限定版本;

[...] [...]

Semantics 语义

In simple assignment (=), the value of the right operand is converted to the type of the assignment expression and replaces the value stored in the object designated by the left operand. 简单赋值 (=)中, 右操作数的值将转换为赋值表达式的类型,并替换存储在左操作数指定的对象中的值。

To perform a deep copy of a struct that contains arrays (without any pointers), a deep copy is simple 要执行包含数组(没有任何指针)的结构的深层副本,深层副本很简单

struct person x = {"Key", "Color", 42};   /*  initialise to something */
struct person y = x;

This doesn't work if the "strings" are pointers though. 如果“字符串”是指针,这不起作用。 It is necessary then to allocate new strings, and then use a function like strcpy() to copy members. 然后有必要分配新的字符串,然后使用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;
}

Some error checking left out of the above (eg need to check that malloc() succeeds before copying). 从上面省略了一些错误检查(例如,需要在复制之前检查malloc()成功)。

If you use strcpy() you have to allocate the memory yourself. 如果你使用strcpy()你必须自己分配内存。 strdup() will do that for you. strdup()会为你做到这一点。 You can use either to create a new memory block which is separate from the original, but naturally strdup() is simpler since it doesn't require a separate malloc(strlen()) call. 您可以使用任何一个创建一个与原始内存块分开的新内存块,但自然strdup()更简单,因为它不需要单独的malloc(strlen())调用。

There is a difference between strcpy() and strdup() . strcpy()strdup()之间存在差异。

  • strdup() allocates space and returns a pointer to the copy of the string, you also have to free() the returned pointer. strdup()分配空格并返回指向字符串副本的指针,您还必须free()返回的指针。

  • strcpy() takes the allocated space and copies the string into it. strcpy()获取分配的空间并将字符串复制到其中。

It seems that in your case it's strcpy() because the fields of your structure are not pointers so you can't assign to them a pointer to allocated space which is what strdup() returns. 看起来在你的情况下它是strcpy()因为你的结构的字段不是指针所以你不能为它们分配一个指向分配空间的指针,这是strdup()返回的。

However, as explained in this answer you actually don't need to. 但是,正如本回答中所解释的那样,您实际上并不需要。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM