C語言中文網 目錄
首頁 > 編程筆記 > C語言筆記 > 指針 閱讀:6,704

指針作為函數參數,C語言指針作為函數參數詳解

我們在前面講指針重要性的時候講過:“指針能使被調函數返回一個以上的結果”。本小節給大家寫一個經典的程序,就是通過一個函數修改主函數中好幾個變量的值。這個程序很經典,把這個程序弄清楚了,指針就算是入門了。在寫這個程序之前先來作一個鋪墊:
# include <stdio.h>
void Swap(int a, int b);  //函數聲明
int main(void)
{
    int i = 3, j = 5;
    Swap(i, j);
    printf("i = %d, j = %d\n", i, j);
    return 0;
}
void Swap(int a, int b)
{
    int buf;
    buf = a;
    a = b;
    b = buf;
    return;
}
大家想一下,執行這個程序是否能互換 i 和 j 的值?不能!i 還是3,j 還是5。

因為實參和形參之間的傳遞是單向的,只能由實參向形參傳遞。被調函數調用完之后系統為其分配的內存單元都會被釋放。所以雖然將 i 和 j 的值傳給了 a 和 b,但是交換的僅僅是內存單元 a 和 b 中的數據,對 i 和 j 沒有任何影響。

“為什么不用 return 語句?”因為 return 語句只能返回一個值,并不能返回兩個值。“將 printf 放在被調函數中不就行了嗎?”我們的目的是互換內存單元 i 和內存單元 j 中的數據。而 printf 的功能僅僅是將結果輸出,并不能改變數據處理的本質,互換的還是單元 a 和單元 b 中的數據。

以上傳遞方式叫作拷貝傳遞,即將內存 1 中的值拷貝到內存 2 中。拷貝傳遞的結果是:不管如何改變內存 2 中的值,對內存 1 中的值都沒有任何影響,因為它們兩個是不同的內存空間。

所以要想直接對內存單元進行操控,用指針最直接,指針的功能很強大。
# include <stdio.h>
void Swap(int *p, int *q);  //函數聲明
int main(void)
{
    int i = 3, j = 5;
    Swap(&i, &j);
    printf("i = %d, j = %d\n", i, j);
    return 0;
}
void Swap(int *p, int *q)
{
    int buf;
    buf = *p;
    *p = *q;
    *q = buf;
    return;
}
輸出結果是:
i = 5, j = 3

此時實參向形參傳遞的不是變量 i 和 j 的數據,而是變量 i 和 j 的地址。其實傳遞指針也是拷貝傳遞,只不過它拷貝的不是內存單元中的內容,而是內存單元的地址,這就是天壤之別了。拷貝地址就可以直接對地址所指向的內存單元進行操作,即此時被調函數就可以直接對變量 i 和 j 進行操作了。有人會說:“被調函數用完就釋放了,不就把 i 和 j 都釋放了嗎?”不是的,當函數調用完之后,釋放的是 p 和 q,不是 i 和 j。p 和 q 中存放的是 i 和 j 的地址。所以 p 和 q 被釋放之后并不會影響 i 和 j 中的值。前面講過,修改指針變量的值不會影響所指向變量中的數據。只不過它們之間的指向關系沒有了而已。 

此外需要注意的是,形參中變量名分別為 p 和 q,變量類型都是 int* 型。所以實參 i 和 j 的地址 &i 和 &j 是分別傳遞給 p 和 q,而不是傳遞給 *p 和 *q。
 
函數參數傳指針和傳數據的區別

綜上所述,如果希望在另外一個函數中修改本函數中變量的值,那么在調用函數時只能傳遞該變量的地址。如果這個變量是普通變量,那么傳遞它的地址就可以直接操作該變量的內存空間。

那么,是不是要定義一個指針變量指向它然后傳遞這個指針變量呢?不用多此一舉。比如有一個“int i;”,如果想傳遞i的地址那就直接傳遞 &i 就行了,不用專門定義一個指針變量指向它,然后再傳遞這個指針變量。

如果要傳遞的變量本身就是一個指針變量怎么辦?如果要操作該指針變量所指向的內存空間是不是要傳遞該指針變量的地址呢?

指針變量本身就是地址,本身就是指向那個內存空間的,所以直接把它傳過去就行了。除非你要改變那個指針變量里面存放的地址,即你要改變指針變量的指向,那么你就必須要傳遞指針變量的地址。

此外,傳指針和傳數據相比還有一個好處就是節約內存。我們知道,傳數據拷貝的是內存單元的數據,如果數據很多的話拷貝過來都要為它們分配內存。而傳指針的話只需要傳遞 4 字節的地址就行了。而且傳數據非常消耗效率,為形參分配內存需要時間,拷貝需要時間,最后結束了返回還是需要時間。前面說過,return 時系統會先自動創建一個臨時變量來存放返回的值。所以傳數據時很消耗效率,而傳指針就是為了提高效率。

事實上,在實際編程中我們都是傳遞指針!往往只有滿足下面這兩個條件的時候我們才會直接傳遞數據而不是傳遞指針,而且這兩個條件缺一不可:
  • 數據很小,比如就一個 int 型變量。
  • 不需要改變它的值,只是使用它的值。

此時不是不能用指針,當然也可以用指針,只是沒有必要。

以后在使用函數的時候,只要函數的參數不滿足上面這兩個條件,那么全部都用指針。此外需要注意的是,數組名本身就是地址,所以如果傳遞數組的話直接傳遞數組名就行了。接收的形參可以定義成數組也可以定義為同類型的指針,這點后面再講。

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

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

底部Logo