C语言中如何在函数内部修改指针指向的地址且外部生效
二级指针修改外部指针变量的原理解析
为什么直接修改char *str不生效
C语言的函数参数默认是值传递,你传入的char*指针本质上也是一个普通变量,和传int类型参数的逻辑完全一致:
- 你在外部定义的
char *p = "xxx";,这个p本身在内存中有独立的存储地址,地址里存的内容是字符串的首地址 - 调用
func(p)的时候,程序会把p存的内容(也就是字符串首地址)拷贝一份给形参str,str是函数栈上的独立变量,和外部的p没有存储层面的关联 - 你在函数内执行
str++操作,修改的只是栈上这个副本str存的地址值,根本不会改动外部p本身的存储内容,所以外部完全看不到变化
二级指针的实现方案和原理
正确的函数定义
要修改外部的某个变量,核心逻辑是把这个变量的地址传入函数内部:比如要修改int变量,就传int*类型的参数;你现在要修改的是char*类型的指针变量,对应的参数类型就需要是指向char*的指针,也就是char**:
// 修改后的函数定义 void func(char **str) { // 数组校验逻辑:先解一层*拿到原字符串指针再操作 if (*str == NULL) return; printf("当前校验字符: %c\n", **str); // 两次解引用拿到字符串对应字符 // 修改原指针本身:解一层*拿到外部原指针变量的存储位置,直接修改它的内容 (*str)++; // 必须加括号,因为++优先级高于*,不加括号会变成对二级指针本身做运算 }
调用方式
外部调用时需要传入原指针的地址:
char *p = "hello"; printf("调用前p指向: %s\n", p); // 输出 hello func(&p); printf("调用后p指向: %s\n", p); // 输出 ello
运行原理拆解
你可以把变量和内存地址做一一对应,就很容易理解逻辑:
- 假设外部的
char *p存储在内存地址0x100上,它存的内容是字符串"hello"的首地址0x200 - 调用
func(&p)的时候,传入的是p的地址0x100,形参str是函数栈上的二级指针,存的内容是0x100 - 执行
*str操作时,就是去0x100这个地址取值,拿到的就是原变量p本身存储的0x200 - 执行
(*str)++操作时,就是把0x100地址上存储的值从0x200改成0x201,等于直接修改了原变量p的存储内容 - 函数退出后,p存储的地址已经是
0x201,所以外部就能看到修改后的效果
注意事项
- 二级指针解引用操作一定要注意运算符优先级,
(*str)++绝对不能写成*str++,后者会先把二级指针str本身的地址+1,再做解引用,完全达不到修改原指针的效果 - 操作前一定要校验
*str是否为NULL,避免空指针访问引发崩溃
内容的提问来源于stack exchange,提问作者SagiBP
相关产品推荐
相关产品推荐

