1. 程式人生 > >C語言參數傳遞(值傳遞、地址傳遞)+二級指針

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

strong 才有 color 示意圖 mage 影響 -s include expr

參數傳遞

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 **來進行交換,讀者可自行修改代碼驗證想一下為什麽?

下面是二級指針示意圖

技術分享圖片

(靈魂畫手已上線)

若有疑問,歡迎留言

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