参数的地址是能够修改的,修改后的地址是不可能传回给调用处的指针变量。也就是说,能够修改参数地址所指的单元的值,这是能够传回到调用处的变量里面的。 #include <stdio.h> #include <stdlib.h> #include <string.h> int subFunc(int arr[3]); //交换两整数 void change(int *data1, int *data2) { int *temp; //交换两数的地址 temp = data1; data1 = data2; //修改参数1的地址 data2 = temp; //修改参数2的地址 //交换后的地址在函数内没问题,但不能传回主程序 printf("change:data1=%d, data2=%d\n", *data1, *data2); return ; } //动态得到内存 //| //改成以下内容即可以传回主程序 void getMemory(int size, char *str) { //| char *getMemory(int size) { //动态分配的内存地址赋给str //| str = (char *)malloc(size); //| return (char *)malloc(size); //| return ; //| } } //| //| //主程序的调用也得改为: p = getMemory(40) ; int main(void) { int x = 25, y = 87 ; change(&x, &y); printf("main:x=%d, y=%d\n", x, y); //x,y未获得交换 getMemory(40, p); //p未获得内存 strcpy(p, "这是小雅的C语言教程"); //这句有错,注释以后才能获得上图结果 free(p) ; return 0; } 2、用局部变量的地址做返回值 这是初学者常犯的错误。小雅在开始作这个例子时,没有用数组,而是用整型变量,结果令我大吃一惊,无论怎么试,结果全是正确的。可小雅明明知道这程序是有毛病的,为何不出错呢?任何事都经不起琢磨,终于明白了其中的缘由,但在这儿不能说,不是小雅卖关子,是由于说了反让初学者糊涂。 #include <stdio.h> int *setData(void) { int arr[3] ; //| static int arr[3] ; arr[0] = 10 ; arr[1] = 35 ; arr[2] = 48 ; return arr ; //局部变量随函数结束而消亡,所以,返回以后是不正确的 } int main(void) { int i ; int *rst ; rst = setData(); for (i=0; i<3; i++) { printf("%3d\n", rst[i]); } return 0; } 上面的错误是将消亡的地址返回,修正的方法能够考虑2种,一是将函数中的数组改成静态的。另外一种办法是再动态申请内存。这样修改以后当然正确,但若是主程序中的rst改成数组,结果又怎样呢?这将致使编译错误。由于数组的地址不能被修改。 3、双重指针做参数 上面第一个例子讲到,不能把指针的地址传给调用处的变量,但实际编程时的确有这种需求,但愿调用一个函数,使得原来的空指针变成有数据内容的指针。 这其实不难实现,你们只要比较一下之前讲到的基本类型(譬如int)做参数时,不能经过参数返回内容,咱们就改为“int *”这样的指针类型做参数,从而解决这个问题。如今咱们只要用双重指针便一样能够解决指针的地址传送的问题。但要注意:“int *”做参数,调用时用“&变量”;“int **”做参数,调用时用“&指针变量”。 #include <stdio.h> #include <stdlib.h> void setData(int **ptr) { int *p = (int *)malloc(3 * sizeof(int)); p[0] = 10, p[1] = 35, p[2] = 48 ; *ptr = p; //注意:是将申请的内存地址赋给*ptr return ; } int main(void) { int i ; int *data = NULL ; //这句有错,应该用指针变量data的地址做参数 setData(data); //| setData(&data); for (i=0; i<3; i++) { printf("%3d\n", data[i]); } return 0; }