C語言參數傳遞(值傳遞、地址傳遞)+二級指針


參數傳遞

C語言參數傳遞一般分為:值傳遞和地址傳遞(本質上只有值傳遞

 

(注意:C語言中沒有引用傳遞,C++才有引用傳遞,因為很多C語言環境是用C++編譯器編譯,使得C看起來支持引用傳遞,導致很多網上很多blog都把引用傳遞歸為C語言參數傳遞的一類,

當使用Microsoft Visual C++ 2010 Express或VC6之類的編譯器時使用引用傳遞就無法編譯通過)

 

值傳遞:

形參是實參的拷貝,改變形參的值並不會影響外部實參的值。從被調用函數的角度來說,值傳遞是單向的(實參->形參)

 

 1 #include <stdio.h>
 2 
 3 void swap(int x, int y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8 
 9  swap(a, b); 10     printf("a=%d\nb=%d\n", a, b); 11 
12     return 0; 13 } 14 void swap(int x, int y) 15 { 16     int t; 17 
18     t = x; 19     x = y; 20     y = t; 21 }

 上述代碼運行后a、b的值並未改變

 

地址傳遞:

形參為指向實參地址的指針,當對形參的指向操作時,就相當於對實參本身進行的操作

 1 #include <stdio.h>
 2 
 3 void swap(int *x, int *y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8 
 9     swap(&a, &b); 10     printf("a=%d\nb=%d\n", a, b); 11 
12     return 0; 13 } 14 void swap(int *x, int *y) 15 { 16     int t; 17 
18     t = *x; 19     *x = *y; 20     *y = t; 21 }

 上述代碼執行后a和b值交換,a=20、b=10

 

易錯點補充:

 1 #include <stdio.h>
 2 
 3 void swap(int *x, int *y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8     int *pp = &a;  9     int *kk = &b; 10  swap(pp, kk); 11     printf("a=%d\nb=%d\n", *pp, *kk); 12 
13     return 0; 14 } 15 void swap(int *x, int *y) 16 { 17     int *t; 18 
19     t = x; 20     x = y; 21     y = t; 22 }

 請讀者想一下,上述代碼執行后a和b的值是否交換,為什么?

上述代碼看起來像交換了指針pp和kk的指向,實際上並沒有

代碼的運行結果a=10、b=20,運行結果是a和b的值並沒有改變,因為這時使用的實參pp,kk是值傳遞,傳遞的是指針的值,以指針pp來說,指針的值是變量a的地址,

指針的值傳入后用形參int *x和int *y接收,這里x和pp雖然都指向變量a的地址,但指針x和pp自身的地址並不相同(意思是x拷貝了一份pp的值),意味着你能改變變量a的值,但是不能改變pp的值(這里與值傳遞相似)

為了更加直觀,清晰的看出值的交換,這里添加一些代碼來顯示內存和變量的值

 

 1 #include <stdio.h>
 2 
 3 void swap(int *x, int *y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8     int *pp = &a;  9     int *kk = &b; 10 
11     printf("a的地址%p----b的地址%p\n\n", &a, &b); 12     printf("pp的值%p----kk的值%p\n", pp, kk); 13     printf("pp的地址%p----kk的地址%p\n\n", &pp, &kk); 14  swap(pp, kk); 15     printf("a = %d\nb = %d", *pp, *kk); 16 
17     return 0; 18 } 19 void swap(int *x, int *y) 20 { 21     int *t; 22     
23     printf("x的值%p----y的值%p\n", x, y); 24     printf("x的地址%p----y的地址%p\n", &x, &y); 25 
26     t = x; 27     x = y; 28     y = t; 29 }

從pp和x的地址可以看出,x和pp是兩塊不同的內存區域,x在swap函數內執行完后並不會對pp值產生任何影響,相當於復制了一份pp的值,如下圖

 

(靈魂畫手已上線)

傳入指針的值雖然不能對指針的值進行修改,但是可以通過地址直接對a的值進行修改也可以實現交換,代碼如下

 1 #include <stdio.h>
 2 
 3 void swap(int *x, int *y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8     int *pp = &a;  9     int *kk = &b; 10 
11  swap(pp, kk); 12     printf("a = %d\nb = %d", *pp, *kk); 13 
14     return 0; 15 } 16 void swap(int *x, int *y) 17 { 18     int t; 19     
20     t = *x; 21     *x = *y; 22     *y = t; 23 }

 

 傳入指針的值和和傳入變量的地址在數值上是一樣的,但是一個是傳值傳遞一個地址傳遞,如下圖

 

(靈魂畫手已經上線)

二級指針

上面提到的參數傳遞方式有,傳入變量的值,傳入變量的地址,傳入指針的值三種參數傳遞方式

下面介紹第四種,傳入指針的地址,上面第二種(傳入變量的地址)和第三種(傳入指針的值)傳遞方式使用的用來接收參數的形參都是int *類型的指針

這里因為傳入的是指針的地址,所以要使用二級指針int **x,因為傳入的指針的地址,實現值的交換的方式就有兩種一種是直接對變量的值進行修改,另一種就是對指針的值進行修改

第一種:直接對變量值進行修改

 

 1 #include <stdio.h>
 2 
 3 void swap(int **x, int **y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8     int *pp = &a;  9     int *kk = &b; 10 
11     swap(&pp, &kk); 12     printf("a = %d\nb = %d", *pp, *kk); 13 
14     return 0; 15 } 16 void swap(int **x, int **y) 17 { 18     int t; 19     
20     t = **x; 21     **x = **y; 22     **y = t; 23 }

 

第二種:對指針的值進行修改

 1 #include <stdio.h>
 2 
 3 void swap(int **x, int **y);  4 
 5 main()  6 {  7     int a = 10, b = 20;  8     int *pp = &a;  9     int *kk = &b; 10 
11     swap(&pp, &kk); 12     printf("a = %d\nb = %d", *pp, *kk); 13 
14     return 0; 15 } 16 void swap(int **x, int **y) 17 { 18     int *t; 19 
20     t = *x; 21     *x = *y; 22     *y = t; 23 }

注意swap函數里用int *來交換指針的值,而不能用int **來進行交換,讀者可自行修改代碼驗證想一下為什么?

下面是二級指針示意圖

(靈魂畫手已上線)

若有疑問,歡迎留言


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM