You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言中含指针成员的结构体传参或赋值为浅拷贝还是深拷贝?

Great question! Let's break this down clearly so you understand exactly what's happening.

C语言中带指针成员的结构体的拷贝行为

在C语言中,带有指针成员的结构体在赋值、或者以值传递方式传递给函数时,默认执行的是浅拷贝——也就是说,只会拷贝结构体里每个成员的"表面值":对于普通成员(比如示例里的int a)是直接拷贝数值;对于指针成员(比如int *b),拷贝的是指针本身存储的内存地址,而不会去拷贝指针指向的那块内存里的实际数据。

和C类似,C语言没有自动的深拷贝机制。你提到C可以通过重载拷贝构造函数和赋值运算符实现深拷贝,但C语言没有类和构造函数的概念,完全依赖开发者手动处理指针指向的内存内容。

示例代码分析

先把你的示例代码整理格式化(注意:代码里用了new是C++语法,C语言通常用malloc,但不影响我们分析拷贝行为):

#include <iostream>
using namespace std;

struct data { int a; int *b; };

void test_func(struct data tes) {
    tes.a = 3;
    int *c = new int[1];
    c[0] = 2;
    tes.b = c;
    std::cout << *tes.b;
}

int main() {
    struct data test;
    int *c = new int;
    *c = 4;
    test.a = 1;
    test.b = c;
    std::cout << *test.b;
    test_func(test);
    std::cout << *test.b;
}

我们一步步拆解执行流程和输出:

  1. 在main函数中,我们给test.b分配了一块内存,里面存的值是4,所以第一个std::cout会输出 4。
  2. 调用test_func(test)时,因为是值传递,会创建tes结构体的副本——这就是浅拷贝:tes.a拷贝了test.a的1,tes.b拷贝了test.b的地址(也就是指向那个存4的内存块)。
  3. 在test_func里,我们修改了tes.a(但这只是修改副本的成员,完全不影响main里的test),然后新分配了一块内存,让tes.b指向这块新内存(里面存2),所以这里的std::cout输出 2。
  4. 函数执行完毕后,tes被销毁,但新分配的那块内存没有被释放(造成内存泄漏)。回到main,test.b仍然指向最初分配的那块存4的内存,所以最后一个std::cout输出 4。

如果是深拷贝的话,test_func的形参tes的b指针会指向一块新的内存,并且把test.b指向的4拷贝过去,但这里显然没有发生这种情况——这就是浅拷贝的典型表现。

如何在C语言中实现深拷贝

如果需要深拷贝带指针的结构体,你必须手动编写逻辑:

  • 为新结构体的指针成员分配足够的内存。
  • 把原指针指向的内容复制到新分配的内存里。
  • 记得在不需要的时候释放这些内存,避免泄漏。

比如,你可以写一个专门的深拷贝函数:

#include <stdlib.h>

struct data deep_copy_data(struct data original) {
    struct data copy;
    copy.a = original.a;
    // 为指针成员分配内存并拷贝内容
    copy.b = malloc(sizeof(int));
    if (copy.b != NULL) {
        *copy.b = *original.b;
    }
    return copy;
}

使用这个函数来拷贝结构体,就能实现深拷贝效果了。

内容的提问来源于stack exchange,提问作者Laxmi Kadariya

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:37:36