C語言中文網 目錄

值傳遞和地址傳遞,C語言函數傳參方式詳解

在 C 語言中,函數的參數傳遞方式有兩種:值傳遞與地址傳遞。下面分別介紹這兩種傳遞形式。

值傳遞

這種方式使用變量、常量、數組元素作為函數參數,實際是將實參的值復制到形參相應的存儲單元中,即形參和實參分別占用不同的存儲單元,這種傳遞方式稱為“參數的值傳遞”或者“函數的傳值調用”。

值傳遞的特點是單向傳遞,即主調函數調用時給形參分配存儲單元,把實參的值傳遞給形參,在調用結束后,形參的存儲單元被釋放,而形參值的任何變化都不會影響到實參的值,實參的存儲單元仍保留并維持數值不變。

來看下面一個調用示例:
#include <stdio.h>
/* 變量x、y為Swap函數的形式參數 */
void Swap(int x, int y)
{
    int tmp;
    tmp = x;
    x = y;
    y = tmp;
    printf("x = %d, y = %d\n", x, y);
}
int main(void)
{
    int a=10;
    int b=20;
     /*變量a、b為Swap函數的實際參數*/
    Swap(a, b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}
在上面這個示例代碼中,實參將值傳遞給形參,形參值發生互換后的值不能回傳給主調函數。因此,主調函數中的數值不變,代碼的運行結果為:
x = 20, y = 10
a = 10, b = 20

對于上面這個示例,或許有人會有如下疑問:上面的示例中明確地把 a、b 分別代入了 x、y 中,并在函數 Swap() 里完成了兩個變量值的交換,為什么 a、b 變量值還是沒有交換。其結果仍然是“a=10,b=20”,而不是“a=20,b=10”呢?

其實,原因很簡單。函數在調用時,隱含地把實參 a 的值賦值給了參數 x,而將實參 b 的值賦值給了參數 y,如下面的代碼所示:
/*將a的值賦值給x(隱含動作)*/
int x = a;
/*將a的值賦值給y(隱含動作)*/
int y = b;
因此,之后在 Swap() 函數體內再也沒有對 a、b 進行任何操作。而在 Swap() 函數體內交換的只是 x、y,并不是 a、b,當然,a、b 的值沒有改變。整個 Swap() 函數調用是按照如下順序執行的:
/*將a的值賦值給x(隱含動作)*/
int x = a;
/*將a的值賦值給y(隱含動作)*/
int y = b;
int tmp;
tmp = x;
x = y;
y = tmp;
printf("x = %d, y = %d\n", x, y);
由此可見,函數只是把 a、b 的值通過賦值傳遞給 x、y,在函數 Swap() 中操作的只是 x、y 的值,并不是 a、b 的值,這也就是所謂的參數的值傳遞。

地址傳遞

這種方式使用數組名或者指針作為函數參數,傳遞的是該數組的首地址或指針的值,而形參接收到的是地址,即指向實參的存儲單元,形參和實參占用相同的存儲單元,這種傳遞方式稱為“參數的地址傳遞”。

地址傳遞的特點是形參并不存在存儲空間,編譯系統不為形參數組分配內存。數組名或指針就是一組連續空間的首地址。因此在數組名或指針作函數參數時所進行的傳送只是地址傳送,形參在取得該首地址之后,與實參共同擁有一段內存空間,形參的變化也就是實參的變化。

來看下面一個調用示例:
void Swap(int *px, int *py)
{
    int tmp;
    tmp = *px;
    *px = *py;
    *py = tmp;
    printf("*px = %d, *py = %d\n", *px, *py);
}
int main(void)
{
    int a=10;
    int b=20;
    Swap(&a, &b);
    printf("a = %d, b = %d\n", a, b);
    return 0;
}
在上面的示例代碼中,函數 void Swap(int*px,int*py) 中的參數 px、py 都是指針類型,在 main 函數中使用語句“Swap(&a,&b)”進行調用,該調用語句將 a 的地址(&a)代入 px,b 的地址(&b)代入 py。很顯然,這里的函數調用有兩個隱含操作:將 &a 的值賦值給參數 px,將 &b 的值賦值給參數 py,如下面的代碼所示:
px = &a;
py = &b;
注意,這里與值傳遞方式存在著很大的區別。在值傳遞方式中,傳遞的是變量 a、b 的內容(即在上面的值傳遞示例代碼中,將 a、b 的內容傳遞給參數 x、y);而這里的地址傳遞方式則是將變量 a、b 的地址值(&a、&b)傳遞給參數 px、py。因此,整個 Swap() 函數調用是按照如下順序執行的:
/*將&a的值賦值給px(隱含動作)*/
px = &a; /* ← */
/*將&b的值賦值給py(隱含動作)*/
py = &b;
int tmp;
tmp = *px;
*px = *py;
*py = tmp;
printf("*px = %d, *py = %d\n", *px, *py);
這樣,有了前兩行的隱含賦值操作,指針變量 px、py 的值已經分別是變量 a、b 的地址值(&a、&b)。接下來,對“*px”“*py”的操作當然也就是對 a、b 變量本身的操作了。所以 Swap() 函數中的交換操作就是對 a、b 值進行交換,這就是所謂的地址傳遞,運行結果為:
*px = 20, *py = 10
a = 20, b = 10

精美而實用的網站,提供C語言C++STLLinuxShellJavaGo語言等教程,以及socketGCCviSwing設計模式JSP等專題。

Copyright ?2011-2018 biancheng.net, 陜ICP備15000209號

底部Logo