You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

结构体指针传递至两个函数并调用malloc后主结构体未获取数据的技术咨询

问题分析与解决方案

你遇到的核心问题是C语言中指针的按值传递特性,确实需要用双指针(或者其他等价方案)来解决,我来一步步拆解你的疑问:

为什么你的代码没生效?

你提到“如果t的地址为0x1000,传递给first()后引用的地址难道不是0x1000吗?”——这里的误解在于:C语言的函数参数都是按值传递的,哪怕你传的是指针,传递的也只是指针变量的副本

具体到你的代码流程:

  1. main里定义的T t;是栈上的结构体变量,假设它的地址是0x1000。
  2. 你调用first(t);的时候,其实是把结构体t的所有值(4个int)拷贝给first的形参t(这是一个指针变量,类型不匹配,编译器应该会报错/警告)——就算忽略类型问题,first里的t是一个独立的指针变量,它的值是0x1000,但这个变量和main里的t完全没关系。
  3. first把这个形参t传给secondsecond里的t又是一个新的副本指针。你在second里执行t = malloc(20);,只是修改了second里这个副本指针的值,让它指向malloc出来的内存(比如0x3000),但mainfirst里的指针/结构体完全不受影响。最后memcpy是把数据写到0x3000的内存里,和main里栈上的0x1000地址毫无关系,所以main里的t自然没有数据。

解决方法

根据你的需求,分两种场景给出方案:

场景1:想在函数中给main里的指针分配动态内存并填充数据

这种情况必须用双指针,或者让函数返回指针,因为我们需要修改原指针变量的值:

方案1:双指针实现

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct _t { int one; int two; int three; int four; } T;
// 假设mydata是预先定义好的T类型数据
T mydata = {1,2,3,4};

void second(T **t) { 
    // *t就是main里的指针变量,修改它的值让它指向malloc的内存
    *t = (T*)malloc(sizeof(T)); 
    memcpy(*t, &mydata, sizeof(T)); // 用sizeof更安全,避免硬编码20
}

void first(T **t) { 
    second(t); 
}

int main() { 
    T *t = NULL; // 定义指针变量,初始化为NULL
    first(&t); // 传递指针的地址(双指针)
    
    // 现在t指向了填充好数据的内存,可以正常使用
    printf("%d %d %d %d\n", t->one, t->two, t->three, t->four);
    
    free(t); // 记得释放动态内存
    return 0;
}

方案2:返回指针实现(更简洁)

如果不想用双指针,可以让函数直接返回malloc的指针:

#include <stdlib.h>
#include <string.h>
#include <stdio.h>

typedef struct _t { int one; int two; int three; int four; } T;
T mydata = {1,2,3,4};

T* second() { 
    T *t = (T*)malloc(sizeof(T)); 
    memcpy(t, &mydata, sizeof(T));
    return t;
}

T* first() { 
    return second(); 
}

int main() { 
    T *t = first(); 
    printf("%d %d %d %d\n", t->one, t->two, t->three, t->four);
    free(t);
    return 0;
}

场景2:只想填充main里已经存在的栈上结构体

如果不需要动态分配内存,只是想把数据拷贝到main里栈上的t中,那根本不需要malloc,直接传递结构体的地址即可(这时候不需要双指针):

#include <string.h>
#include <stdio.h>

typedef struct _t { int one; int two; int three; int four; } T;
T mydata = {1,2,3,4};

void second(T *t) { 
    memcpy(t, &mydata, sizeof(T)); // 直接拷贝到传入的地址(main里t的地址)
}

void first(T *t) { 
    second(t); 
}

int main() { 
    T t; // 栈上的结构体
    first(&t); // 传递结构体的地址,而不是结构体本身
    
    printf("%d %d %d %d\n", t.one, t.two, t.three, t.four);
    return 0;
}

关键总结

  • C语言中所有参数都是按值传递的,指针也不例外——传递指针时,函数拿到的是指针的副本,修改副本不会影响原指针。
  • 如果要在函数中修改原指针的值(比如让它指向新的内存),必须传递指针的地址(双指针),或者让函数返回新的指针。
  • 如果你只是想修改指针指向的内存内容(而不是指针本身的值),传递单指针就足够了。

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

火山引擎 最新活动