【例21.23】函數參數傳遞變量值、地址值和指針的區別。
#include <stdio.h> void Add (int a , int *b , int *p ) { printf (\"Add :&a=%#x ,&b=%#x , p=%#xn\" , &a , b , p ); a = a + *b ; *b = a * *b ; *p = a + *b ; printf (\"In Add :a=%d ,b=%d , *p=%dn\" , a , *b ,*p ); } void main () { int a=5 , b=8 , *p ; p=&b ; printf (\"main :&a=%#x ,&b=%#x , p=%#xn\" , &a , &b , p ); printf (\"main :a=%d ,b=%d , *p=%dn\" , a , b ,*p ); Add (a , &b , p ); printf (\"main :a=%d , b=%d , *p=%dn\" , a , b ,*p ); }
程序運行結果如下:
main :&a=0x12ff7c ,&b=0x12ff78 , p=0x12ff78 main :a=5 ,b=8 , *p=8 Add :&a=0x12ff1c ,&b=0x12ff78 , p=0x12ff78 In Add :a=13 ,b=117 , *p=117 main :a=5 , b=117 , *p=117 // 傳值不改變變量a 的值
由運行結果可以驗證,在函數里,必須將傳值的參數複製到函數里以完成形實結合,供被調函數使用,所以變量a在主函數和Add函數里的地址是不一樣的,系統需要在被調用函數里為變量a重新分配地址,當離開函數時,又把函數里的a值丟掉,將原來調用時的形參值複製給變量a,即恢復原來的實參值。傳遞地址值和指針時,系統不為它們分配地址而仍然使用原來的地址,所以也不需要複製數據。同理,當調用返回時,也不需要複製數據。
【例21.24】函數參數傳遞結構變量值、地址值和指針的區別。
#include <stdio.h> #include <stdlib.h> struct LIST{ int a , b ; } ; void Add (struct LIST a , struct LIST *pb , struct LIST *p ) { printf (\"Add :&a=%#x ,&b=%#x , p=%#xn\" , &a , pb , p ); a.a = a.a + pb->a ; a.b = a.b + pb->b ; p->a=pb->a + pb->a ; p->b=pb->b+ pb->b ; printf (\"In Add :a.a=%d , a.b=%dn\" , a.a ,a.b ); printf (\"In Add :pb->a=%d , pb->b=%dn\" , pb->a , pb->b ); printf (\"In Add :p->a=%d , p->b=%dn\" , p->a , p->b ); } void main () { struct LIST a={1 , 3} , b= {2 , 4} , *p=&b ; printf (\"main :&a=%#x ,&b=%#x , p=%#xn\" , &a , &b , p ); printf (\"main :a.a=%d , a.b=%dn\" , a.a ,a.b ); printf (\"main :b.a=%d , b.b=%dn\" , b.a ,b.b ); printf (\"main :p->a=%d , p->b=%dn\" , p->a , p->b ); Add (a , &b , p ); printf (\"main :a.a=%d , a.b=%dn\" , a.a ,a.b ); printf (\"main :b.a=%d , b.b=%dn\" , b.a ,b.b ); printf (\"main :p->a=%d , p->b=%dn\" , p->a , p->b ); }
程序運行結果如下:
main :&a=0x12ff78 ,&b=0x12ff70 , p=0x12ff70 main :a.a=1 , a.b=3 main :b.a=2 , b.b=4 main :p->a=2 , p->b=4 Add :&a=0x12ff10 ,&b=0x12ff70 , p=0x12ff70 In Add :a.a=3 , a.b=7 In Add :pb->a=4 , pb->b=8 In Add :p->a=4 , p->b=8 main :a.a=1 , a.b=3 // 傳值不改變結構變量a 的值 main :b.a=4 , b.b=8 main :p->a=4 , p->b=8
由輸出結果可知,結論與上例一樣。
其實,通過彙編代碼,可以清楚地看到在被調函數里如何將主函數結構變量的值複製給被調用的結構變量。
【例21.25】函數參數傳遞結構數組地址值和指針的例子。
#include <stdio.h> #include <stdlib.h> struct LIST{ int a , b ; }a[2] = {{1 , 3} , {2 , 4}} , *p=a ; void Add (struct LIST *pb , struct LIST *p ) { int i = 0 ; printf (\"Add :&a=%#x , p=%#xn\" , pb , p ); for ( i=0 ; i < 2 ; i++ , p++ ) { a[i].a = a[i].a + p->a ; a[i].b = a[i].b + p->b ; } p=a ; for ( i=0 ; i < 2 ; i++ , p++ ) { printf (\"In Add :a[i].a=%d , a[i].b=%dn\" , a[i].a , a[i].b ); printf (\"In Add :p->a=%d , p->b=%dn\" , p->a , p->b ); } p=a ; } void main () { int i=0 ; printf (\"main :&a=%#x , p=%#xn\" , &a , p ); for ( i=0 ; i < 2 ; i++ , p++ ) { printf (\"main :a[i].a=%d , a[i].b=%dn\" , a[i].a ,a[i].b ); printf (\"main :p->a=%d , p->b=%dn\" , p->a , p->b ); } p=a ; Add (a , p ); for ( i=0 ; i < 2 ; i++ , p++ ) { printf (\"main :a[i].a=%d , a[i].b=%dn\" , a[i].a ,a[i].b ); printf (\"main :p->a=%d , p->b=%dn\" , p->a , p->b ); } }
程序運行結果如下:
main :&a=0x423308 , p=0x423308 main :a[i].a=1 , a[i].b=3 main :p->a=1 , p->b=3 main :a[i].a=2 , a[i].b=4 main :p->a=2 , p->b=4 Add :&a=0x423308 , p=0x423308 In Add :a[i].a=2 , a[i].b=6 In Add :p->a=2 , p->b=6 In Add :a[i].a=4 , a[i].b=8 In Add :p->a=4 , p->b=8 main :a[i].a=2 , a[i].b=6 main :p->a=2 , p->b=6 main :a[i].a=4 , a[i].b=8 main :p->a=4 , p->b=8
由此可見,如果數組維數大,使用結構指針比直接傳遞數組地址值更方便。