两种指针传参方式一触发段错误一正常,差异何在?
为什么两种指针传参方式结果不同?
这是个非常典型的C语言指针层级和参数传递问题,我来给你拆解清楚:
先看第一种出错的写法
double ****A; my_function(A);
这里你声明了一个四级指针变量A,但注意:你只是声明了它,完全没有给它初始化——也就是说A现在是个野指针,里面存的是随机的内存地址。
当你把A传给my_function时,C语言是值传递:函数会拿到A当前值的一个副本。如果my_function内部尝试对这个指针做解引用操作(比如*A = malloc(...)),本质是在访问那个随机的无效内存地址,直接触发段错误完全是意料之中的事。
再看第二种正常运行的写法
double ***A; my_function(&A);
这里的A是三级指针变量,&A取的是这个变量在栈上的有效内存地址——而这个地址的类型正好是double****(和第一种写法里A的类型一致)。
这时候传给my_function的是一个完全合法的内存地址:指向栈上的A变量。函数内部如果做*A = malloc(...),本质是修改栈上A变量的值,让它指向一块你分配的堆内存,这完全是合法操作,自然不会触发段错误。
核心逻辑:C语言的「值传递」特性
这个问题的本质和修改普通变量的逻辑一模一样,只是多了几层指针:
- 如果你想让函数修改一个
int变量的值,不能直接传变量本身,得传它的地址(int*) - 同理,如果你想让函数修改一个
double***变量的指向,就得传它的地址(也就是double****)
举个简化版的例子帮你理解:
// 错误:传值,修改的是副本,外部变量不受影响 void set_int_wrong(int x) { x = 42; } int num = 0; set_int_wrong(num); // num还是0 // 正确:传地址,修改的是外部变量本身 void set_int_right(int *x) { *x = 42; } int num = 0; set_int_right(&num); // num变成42
你的指针传参问题就是这个逻辑的多层延伸,只是把int换成了double***而已。
总结一下
- 第一种写法里的A是未初始化的野指针,传递给函数后操作的是无效内存
- 第二种写法传递的是有效变量的地址,函数可以合法修改外部指针的指向
- 关键要记住:C语言所有参数都是值传递,要修改外部变量(包括指针变量),必须传递它的地址
内容的提问来源于stack exchange,提问作者DJames
相关产品推荐
相关产品推荐

