C語言函數調用與參數傳遞

來源:文萃谷 1.05W

函數是C語言中的基本組成單位,一個較大的C程序一般可分為若干個程序模塊,實現某一特定功能的模塊主要由函數來完成。下面是小編收集整理的C語言函數調用與參數傳遞,歡迎閲讀,希望大家能夠喜歡。

C語言函數調用與參數傳遞

1、主調函數與被調函數

計算機在執行C程序時總是從main函數開始,如果遇到要調用某個函數,則主函數稱為主調函數,被調用者稱為被調函數。一個C程序可由一個main函數和若干個其他函數構成,main函數用來解決整個問題,它調用解決小問題的其他函數,其他函數也可以相互調用。調用者就是主調函數,被調者就是被調函數,應當注意,main函數只能由系統調用。

2、實際參數與形式參數

在調用有參函數時,主調函數和被調函數之間有數據傳遞關係。在主調函數中進行函數調用時,函數名後面括弧中的參數稱為實際參數,簡稱實參。在定義函數時函數名後面括弧中的變量名就是形式參數,簡稱形參。即實參出現在函數調用中,形參出現在函數定義中。主調函數通過函數調用將實參中的數據傳遞給被調函數的形參,從而實現函數間的數據傳遞。另外實參與形參進行數據傳遞時,系統要求實參與形參在數量、類型、順序應嚴格保持一致,這一點在使用上要特別注意。

3、變量存儲類型與作用域

主調函數和被調函數數據傳遞往往要通過變量進行,不同的變量類型影響數據的處理結果。C語言中變量按存儲時分配的空間不同可以分為自動變量,寄存器變量,靜態變量和外部變量。按變量的生命週期可以分為局部變量和全局變量,局部變量是在一個函數內部定義的變量,在存儲器的動態存儲區進行分配空間,作用域只在本函數內部有效,比如在主函數裏定義的自動變量,寄存器變量,函數中的形式參數等都屬於局部變量,在函數調用時,系統才為其分配存儲空間,函數調用結束後,空間釋放。而對於靜態型局部變量是程序編譯時由系統在存儲器的靜態存儲區為其分配存儲空間,函數調用結束後,空間不釋放,其值要保留到程序退出。全局變量是在程序整個運行期間都要佔用內存,所以它是全程有效,貫穿於主調函數與被調函數全過程,其值也要保留到程序退出為止。

4、參數傳遞的本質與屬性

函數參數傳遞的過程,本質上是一種賦值過程即值傳遞過程,在調用函數之前,函數的每個實際參數將被複制,複製的值代替對應的形式參數。所以形參實際上得到的不是實參本身,而是實參的值或者實參所代表的值。因此,如果一個變量傳遞給一個函數,這個變量在調用環境中所存儲的值並不會被函數修改,所以形參的值不會反過來影響實參,即實參與形參值傳遞是單向性的。這兩個問題是學習和理解函數參數傳遞的根本,很多學習C語言的人對這兩個問題不是很理解,下面舉例説明函數調用時參數傳遞過程。

4.1 數值傳遞

當變量為普通變量時,函數實參可以是自動局部變量,靜態局部變量,數組元素,寄存器變量,結構體變量,結構體變量成員,常量等形式,函數形參為對應類型的變量,調用函數時,由系統給形參分配存儲單元,存放從實參複製過來的數值。函數調用結束後,形參存儲單元釋放。

例題1:

#include

void func1(int x)

{++x;

printf (“%d”,x);

int main()

{int n=10;

func1(n);

printf (“%d”,n);

return 0 ;

例題1中main函數調用func1函數時,把實參n的值10(注意不是n)傳給了形參x,x在func1函數中進行增1運算, 這時x的值發生了改變,但該值不能返回到實參n中,因為x是func1函數內部定義的變量,屬於局部變量,調用函數時,系統為x變量在存儲器的動態存儲區分配存儲空間,函數調用結束後,x變量被釋放,數值被清,故n值不變,體現了傳值的單向性。

4.2 地址值傳遞

地址值傳遞是指實參與形參之間傳遞的數據是地址,與數值傳遞不同的是,地址值傳遞的是形參接收實參地址的複製值,而不是實參值本身。另外,地址值傳遞方式中系統不為形式參數變量分配存儲空間,這一點也與數值傳遞方式不同。因為函數調用完成數據傳遞後,實參與形參擁有相同的變量地址,它們指向同一變量單元,該變量在主調函數定義時已經分配了存儲空間,形參只是接收了它的一個地址值,並沒有接收變量本身。根據參數類型的不同,地址值傳遞方式常見的有如下幾種情況。

4.2.1 實參為變量地址,形參為指針

例題2:

#include

void func2( int *x,int *y)

{

x=y;

}

int main()

{ int a=2,b=3;

func2(&a,&b);

printf ("%d,%d",a,b);

return 0;

}

例題2中在主調函數中將a,b的地址值傳給了形參指針x和y,在被調函數中將y值賦給了x,這時x的值發生了改變,x存放的是y的存儲地址,即x指向3,但是這個指向並不能返回到主調函數。因為這個地址值在函數調用結束後被釋放,其值消失。當然,如果想在被調函數中修改主調函數中實參變量的值,需要修改指針變量x和y所指向的地址中的內容。比如將x=y改為*x=*y,即可達到修改實參變量的目的,但是必須清楚,雖然被調函數通過指針可以修改主調函數中的值,但這只是一種間接訪問數據的形式而已,實參向形參傳遞數據的單向性是不變的。

4.2.2 實參為數組名,形參為指針

在C語言中,數組名是一個地址,而且是一個地址常量,它代表的是該數組元素的首地址,不是一個變量。當使用數組名作為實參時,實參的`值就是數組的首地址,形參指針接收的也是該數組的首地址,被調函數通過形參指針的變化來訪問主調函數中數據。

例題3:

#include

void func3( int *x,int y)

{ int i;

for(i=0;i printf("%4d",*x++);

}

int main()

{ int a[5]={1,2,3,4,5},b=5;

func3(a,b);

return 0;

}

例題3中形參有兩個,第一個表示形參接收一個整型類型的地址,第二個表示接收一個整型類型的數據,至於實參是不是一個指針,是不是一個整型變量,形式參數並不理會,只管數據的類型是否匹配。而從主調函數中可以看出,實參為數組名(地址)和整型數據(整型類型),符合參數傳遞規則。這樣發生函數調用時,形參指針指向了數組a的第一個元素,通過循環程序,輸出了數組a的所有元素。

這裏還有一個問題,形參指針x在被調函數中的值發生了變化,這個值是不會返回給實參的,很明顯,實參中的第一個參數a是數組名,代表一個地址常量,肯定不能對它進行賦值操作,這裏進一步驗證了實參與形參值傳遞是單向性的。

4.2.3 實參為數組名,形參為數組名

當實參與形參均為數組名時,這種方式跟其他的地址值傳遞方式是一樣的,系統也是不給形參數組分配內存空間,而是將形參數組名處理成一個指針,因此形參數組並不存在。當發生函數調用時,實參數組只是把首地址賦給形參數組名。這樣形參數組名也指向實參數組,兩個數組共同佔有一段內存空間。因此通過改變形參數組元素的值來達到改變實參數組元素的目的。

例題4:

#include

void func4(int b[5])

{

b[0]=5;

b[1]=4;

b[2]=3;

b[3]=2;

b[4]=1;

}

int main( )

{int i;

int a[5]={1,2,3,4,5};

func4(a);

for(i=0;i<5;i++)

printf("%4d",a[i]);

return 0;

}

例題中實參與形參均為數組名,調用函數時,實參數組的首地址複製後給了形參數組,使形參數組名指向了實參數組,當改變形參數組元素值時,實參元素值必然改變,因為實參數組和形參數組是同一塊存儲單元。

4.2.4 實參為指針,形參為數組名

4.2.5 實參為指針,形參為指針

對於(1),(5)這兩種情況比較好理解,實參為指針,其值為地址,所以形參接收的也是地址,實參與形參類型匹配,可以進行數據傳遞,在此不一一介紹。

熱門標籤