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

为何直接传char*无法在函数内malloc赋值,结构体中char*却可行?

C语言指针传值与结构体指针的差异分析

第一段代码的报错原因

先看这段运行报错的代码:

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

void func(char* dest, const char* src)
{
    dest = malloc(strlen(src) + 1);
    strcpy(dest, src);
}

int main()
{
    char* name0;
    char* name1 = "Jam";

    func(name0, name1);
    puts(name0);
    
    free(name0);
    return 0;
}

问题根源在于C语言的参数传值机制:

  • 当把name0传给func的dest参数时,C会创建一个name0的副本,函数内的dest和main里的name0是完全独立的两个指针变量。
  • 函数里执行dest = malloc(...)只是修改了这个副本的指向,main中的name0还是未初始化的野指针。
  • 后续puts(name0)会访问野指针指向的非法内存,触发运行错误;free(name0)对野指针操作,同样会引发异常。

第二段代码的解决原理

再看这段能正常运行的代码:

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

struct st
{
    char* name;
};

void func(struct st* st1, const struct st* st2);

int main(void)
{
    struct st name0, name1;
    name1.name = "Jam";

    func(&name0, &name1);

    puts(name0.name);

    free(name0.name);
    name0.name = NULL;

    exit(0);
}

void changename(struct st* st1, const struct st* st2)
{
    st1->name = malloc(strlen(st2->name) + 1);
    if(st1->name == NULL)
        exit(1);
    strcpy(st1->name, st2->name);
}

核心逻辑是传递结构体指针,直接修改原结构体的成员变量:

  • 传给changename的是name0的地址(&name0),函数内的st1是指向原结构体的指针,而非副本。
  • st1->name直接访问原结构体name0中的name指针成员,执行st1->name = malloc(...)时,修改的是原结构体里name变量的指向,main中的name0.name会同步获取到新分配的内存地址。
  • 因此后续puts(name0.name)能正确访问合法内存,free也能正常释放资源,不会出现野指针问题。

本质区别总结

  • 直接传char*时,函数操作的是指针的副本,无法改变外部原指针的指向;
  • 传结构体指针时,函数通过指针直接操作原结构体的成员(包括其中的char*),修改的是原成员的指向,外部能直接感知到变化。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.13 07:55:31