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

下面是二級指針示意圖

  • 提醒:扣緊定義,咬定青山不放松,****p=***(*p)=**(**p)=*(***p)=(****p)不管幾層,我一層層看 抽象時,畫圖,畫圖,畫圖---什么事情說三遍?


免責聲明!

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



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