如何在 C 语言中实现结构体的深拷贝

本文涉及的产品
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
Redis 开源版,标准版 2GB
推荐场景:
搭建游戏排行榜
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
简介: 在C语言中实现结构体的深拷贝,需要手动分配内存并逐个复制成员变量,确保新结构体与原结构体完全独立,避免浅拷贝导致的数据共享问题。具体方法包括使用 `malloc` 分配内存和 `memcpy` 或手动赋值。
  1. 手动实现深拷贝

    • 基本思路
      • 对于结构体中的基本数据类型成员(如intfloatchar等),直接进行赋值操作。
      • 对于指针类型成员,需要重新分配内存空间,并将原指针指向的数据复制到新分配的内存空间中。
    • 示例代码

      #include <stdio.h>
      #include <stdlib.h>
      #include <string.h>
      
      // 定义一个包含指针成员的结构体
      struct Person {
             
          char *name;
          int age;
      };
      
      // 深拷贝函数
      struct Person deepCopyPerson(struct Person src) {
             
          struct Person dest;
          // 为新的name成员分配内存空间
          dest.name = (char *)malloc(strlen(src.name)+1);
          // 复制name字符串
          strcpy(dest.name, src.name);
          // 复制age成员
          dest.age = src.age;
          return dest;
      }
      
      int main() {
             
          struct Person p1;
          p1.name = (char *)malloc(10);
          strcpy(p1.name, "Alice");
          p1.age = 25;
      
          struct Person p2 = deepCopyPerson(p1);
          // 修改p2的成员
          p2.age = 30;
          p2.name[0] = 'B';
          // 输出结果
          printf("p1: name = %s, age = %d\n", p1.name, p1.age);
          printf("p2: name = %s, age = %d\n", p2.name, p2.age);
      
          // 释放内存
          free(p1.name);
          free(p2.name);
          return 0;
      }
      
    • 解释
      • 在上述代码中,定义了struct Person结构体,其中包含一个字符指针name和一个整数age
      • deepCopyPerson函数用于实现深拷贝。首先创建一个新的struct Person结构体dest。然后为dest.name分配足够的内存空间,大小为src.name字符串长度加1(用于存储字符串结束符\0)。接着使用strcpy函数将src.name中的字符串复制到dest.name中,再将src.age赋值给dest.age
      • main函数中,首先初始化p1结构体,然后通过deepCopyPerson函数创建p2结构体,这是一个深拷贝的结果。之后修改p2的成员,可以看到p1的成员不受影响。最后,需要释放p1.namep2.name所指向的内存,以避免内存泄漏。
  2. 利用库函数实现部分功能辅助深拷贝

    • 使用memcpy函数(适用于简单的结构体)

      • 基本思路:当结构体中没有指针成员或者指针成员所指向的数据不需要特别处理(如只包含固定大小的数组)时,可以使用memcpy函数来复制结构体。
      • 示例代码

        #include <stdio.h>
        #include <string.h>
        
        struct Data {
                 
            int numbers[5];
        };
        
        struct Data deepCopyData(struct Data src) {
                 
            struct Data dest;
            // 使用memcpy进行拷贝
            memcpy(&dest, &src, sizeof(struct Data));
            return dest;
        }
        
        int main() {
                 
            struct Data d1 = {
                  {
                 1, 2, 3, 4, 5} };
            struct Data d2 = deepCopyData(d1);
            d2.numbers[0] = 10;
            // 输出结果
            printf("d1: ");
            for(int i = 0; i < 5; i++) {
                 
                printf("%d ", d1.numbers[i]);
            }
            printf("\n");
            printf("d2: ");
            for(int i = 0; i < 5; i; i++) {
                 
                printf("%d ", d2.numbers[i]);
            }
            printf("\n");
            return 0;
        }
        
      • 解释
        • 定义了struct Data结构体,其中包含一个整数数组numbers。在deepCopyData函数中,使用memcpy函数将src结构体的内容复制到dest结构体中。memcpy函数会按照字节数进行复制,这里复制的字节数是sizeof(struct Data),确保完整地复制结构体的内容。
        • main函数中,初始化d1结构体,然后通过deepCopyData函数创建d2结构体。修改d2结构体中的数组元素,d1不受影响,这也实现了一种类似深拷贝的效果(在没有指针成员的情况下)。

需要注意的是,在使用memcpy函数时,要确保目标结构体已经正确初始化并且有足够的空间来接收复制的数据。同时,对于包含指针成员的复杂结构体,单纯使用memcpy可能无法实现真正的深拷贝,需要结合手动内存分配和数据复制来完成。

相关文章
|
21天前
|
存储 大数据 编译器
C语言:结构体对齐规则
C语言中,结构体对齐规则是指编译器为了提高数据访问效率,会根据成员变量的类型对结构体中的成员进行内存对齐。通常遵循编译器默认的对齐方式或使用特定的对齐指令来优化结构体布局,以减少内存浪费并提升性能。
|
25天前
|
编译器 C语言
共用体和结构体在 C 语言中的优先级是怎样的
在C语言中,共用体(union)和结构体(struct)的优先级相同,它们都是用户自定义的数据类型,用于组合不同类型的数据。但是,共用体中的所有成员共享同一段内存,而结构体中的成员各自占用独立的内存空间。
|
25天前
|
存储 C语言
C语言:结构体与共用体的区别
C语言中,结构体(struct)和共用体(union)都用于组合不同类型的数据,但使用方式不同。结构体为每个成员分配独立的内存空间,而共用体的所有成员共享同一段内存,节省空间但需谨慎使用。
|
30天前
|
编译器 C语言 C++
C语言结构体
C语言结构体
25 5
|
1月前
|
编译器 Linux C语言
C语言 之 结构体超详细总结
C语言 之 结构体超详细总结
18 0
|
1月前
|
存储 编译器 Linux
深入C语言:探索结构体的奥秘
深入C语言:探索结构体的奥秘
|
1月前
|
存储 编译器 C语言
c语言回顾-结构体(2)(下)
c语言回顾-结构体(2)(下)
28 0
|
1月前
|
存储 编译器 程序员
c语言回顾-结构体(2)(上)
c语言回顾-结构体(2)(上)
28 0
|
1月前
|
存储 C语言
c语言回顾-结构体
c语言回顾-结构体
16 0
|
存储 C语言
【C语言】 条件操作符 -- 逗号表达式 -- []下标访问操作符,()函数调用操作符 -- 常见关键字 -- 指针 -- 结构体
【C语言】 条件操作符 -- 逗号表达式 -- []下标访问操作符,()函数调用操作符 -- 常见关键字 -- 指针 -- 结构体