參數的地址是能夠修改的,修改後的地址是不可能傳回給調用處的指針變量。也就是說,能夠修改參數地址所指的單元的值,這是能夠傳回到調用處的變量裏面的。 #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; }