为何调用change_it()无效果?请解释并修正给定C语言代码
咱们先看看这段代码里的核心问题:调用change_it()后,main里的数组a的地址完全没变化,这是因为你误解了C语言里数组作为函数参数的传递方式,以及数组名的本质。
为什么change_it()没起作用?
这里有两个关键要点得捋清楚:
数组参数的退化与值传递
当你把数组a传给change_it(int[])时,C语言会自动把数组参数退化成指向数组首元素的指针(也就是int*)。而且这个指针是通过值传递给函数的——也就是说,change_it里的a是一个局部指针变量,它只是main里数组首地址的副本。你在change_it里给a赋值q,只是修改了这个局部指针的值,完全不会影响main里的数组a(甚至main里的数组名a本身是个常量指针,根本不能被赋值)。数组名的本质
在main里,a是数组名,它代表数组首元素的地址,但它是一个常量,不能被重新赋值(比如你写a = q;在main里会直接编译报错)。所以原代码里change_it的写法从根本上就没法修改原数组的地址。
另外提一句,原代码里int *p=1;是非法的——你把整数1直接赋值给指针,这会让p指向一个无效的内存地址,运行时很可能崩溃,这个也得改。
修正后的代码
如果你想让函数修改main里某个指针的指向(比如例子里的p),我们需要传递指针的指针(因为要修改指针本身,得传它的地址)。这里调整一下代码:
#include <stdio.h> // 调整参数为指针的指针 void change_it(int**); int main() { int a[5]; // 初始化p指向数组a的首地址,替换非法的初始值1 int *p = a; printf("p has the value %u \n", (unsigned int)p); // 传递p的地址给函数 change_it(&p); printf("p has the value %u \n", (unsigned int)p); return 0; } void change_it(int** ptr) { int i=777; // 修改ptr指向的指针(也就是main里的p)的指向 *ptr = &i; // 注意:这里i是局部变量,函数结束后会销毁,实际使用中要注意野指针问题,此处仅作演示 }
补充说明
上面的修正代码里,change_it接收的是int**类型的参数,也就是指针的指针。通过*ptr = &i;,我们直接修改了main里p的指向。不过要注意:i是change_it里的局部变量,函数执行完后这个变量的内存会被释放,所以p最后会变成野指针,实际开发中如果要让指针长期有效,得用全局变量、静态变量或者动态分配内存(比如malloc)。
内容的提问来源于stack exchange,提问作者Shahriar Dipto

