函數的參數—實參|形參
在函數定義中出現的參數可以看做是一個占位符,它沒有數據,只能等到函數被調用時接收傳遞進來的數據,所以稱為形式參數,簡稱形參。
函數被調用時給出的參數包含了實實在在的數據,會被函數內部的代碼使用,所以稱為實際參數,簡稱實參。
形參和實參的功能是傳遞數據,發生函數調用時,實參的值會傳遞給形參。
形參和實參有以下幾個特點:
-
形參變量只有在函數被調用時才會分配內存,調用結束后,立刻釋放內存,所以形參變量只有在函數內部有效,不能在函數外部使用。
-
實參可以是常量、變量、表達式、函數等,無論實參是何種類型的數據,在進行函數調用時,它們都必須有確定的值,以便把這些值傳送給形參,所以應該提前用賦值、輸入等辦法使實參獲得確定值。
-
實參和形參在數量上、類型上、順序上必須嚴格一致,否則會發生“類型不匹配”的錯誤。當然,如果能夠進行自動類型轉換,或者進行了強制類型轉換,那么實參類型也可以不同於形參類型。
-
函數調用中發生的數據傳遞是單向的,只能把實參的值傳遞給形參,而不能把形參的值反向地傳遞給實參;換句話說,一旦完成數據的傳遞,實參和形參就再也沒有瓜葛了,所以,在函數調用過程中,形參的值發生改變並不會影響實參。
1 #include <stdio.h> 2 3 //計算從1加到n的值 4 int sum(int n){ 5 int i; 6 for(i=n-1; i>=1; i--){ 7 n+=i; 8 } 9 printf("The inner n = %d\n",n); 10 return n; 11 } 12 13 int main(){ 14 int m, total; 15 printf("Input a number: "); 16 scanf("%d", &m); 17 total = sum(m); 18 printf("The outer m = %d \n", m); 19 printf("1+2+3+...+%d+%d = %d\n", m-1, m, total); 20 return 0; 21 }
運行結果:
Input a number: 100↙
The inner n = 5050
The outer m = 100
1+2+3+...+99+100 = 5050
通過 scanf 輸入 m 的值,作為實參,在調用 sum() 時傳送給形參 n。
從運行情況看,輸入 m 值為100,即實參 m 的值為100,把這個值傳給函數 sum 時,形參 n 的初始值也為100,在函數執行過程中,形參 n 的值變為 5050。函數運行結束后,輸出實參 m 的值仍為100,可見實參的值不隨形參的變化而變化。
摘自http://c.biancheng.net/cpp/html/57.html
局部變量
定義在函數內部的變量稱為局部變量(Local Variable),它的作用域僅限於函數內部, 離開該函數后就是無效的,再使用就會報錯。
- 在 main 函數中定義的變量也是局部變量,只能在 main 函數中使用;同時,main 函數中也不能使用其它函數中定義的變量。main 函數也是一個函數,與其它函數地位平等。
- 形參變量、在函數體內定義的變量都是局部變量。實參給形參傳值的過程也就是給局部變量賦值的過程。
- 可以在不同的函數中使用相同的變量名,它們表示不同的數據,分配不同的內存,互不干擾,也不會發生混淆。
- 在語句塊中也可定義變量,它的作用域只限於當前語句塊。
1 int f1(int a){ 2 int b,c; //a,b,c僅在函數f1()內有效 3 return a+b+c; 4 } 5 int main(){ 6 int m,n; //m,n僅在函數main()內有效 7 return 0; 8 }
全局變量
在所有函數外部定義的變量稱為全局變量(Global Variable),它的作用域默認是整個程序,也就是所有的源文件,包括 .c 和 .h 文件。
1 int a, b; //全局變量 2 void func1(){ 3 //TODO: 4 } 5 6 float x,y; //全局變量 7 int func2(){ 8 //TODO: 9 } 10 11 int main(){ 12 //TODO: 13 return 0; 14 }
a、b、x、y 都是在函數外部定義的全局變量。C語言代碼是從前往后依次執行的,由於 x、y 定義在函數 func1() 之后,所以在 func1() 內無效;而 a、b 定義在源程序的開頭,所以在 func1()、func2() 和 main() 內都有效。
局部變量和全局變量的綜合示例
1 #include <stdio.h> 2 3 int n = 10; //全局變量 4 5 void func1(){ 6 int n = 20; //局部變量 7 printf("func1 n: %d\n", n); 8 } 9 10 void func2(int n){ 11 printf("func2 n: %d\n", n); 12 } 13 14 void func3(){ 15 printf("func3 n: %d\n", n); 16 } 17 18 int main(){ 19 int n = 30; //局部變量 20 func1(); 21 func2(n); 22 func3(); 23 //代碼塊由{}包圍 24 { 25 int n = 40; //局部變量 26 printf("block n: %d\n", n); 27 } 28 printf("main n: %d\n", n); 29 30 return 0; 31 }
運行結果:
func1 n: 20
func2 n: 30
func3 n: 10
block n: 40
main n: 30
代碼中雖然定義了多個同名變量 n,但它們的作用域不同,在內存中的位置(地址)也不同,所以是相互獨立的變量,互不影響,不會產生重復定義(Redefinition)
錯誤。
1) 對於 func1(),輸出結果為 20,顯然使用的是函數內部的 n,而不是外部的 n;func2() 也是相同的情況。
當全局變量和局部變量同名時,在局部范圍內全局變量被“屏蔽”,不再起作用。或者說,變量的使用遵循就近原則,如果在當前作用域中存在同名變量,就不會向更大的作用域中去尋找變量。
2) func3() 輸出 10,使用的是全局變量,因為在 func3() 函數中不存在局部變量 n,所以編譯器只能到函數外部,也就是全局作用域中去尋找變量 n。
3) 由{ }
包圍的代碼塊也擁有獨立的作用域,printf() 使用它自己內部的變量 n,輸出 40。
4) C語言規定,只能從小的作用域向大的作用域中去尋找變量,而不能反過來,使用更小的作用域中的變量。對於 main() 函數,即使代碼塊中的 n 離輸出語句更近,但它仍然會使用 main() 函數開頭定義的 n,所以輸出結果是 30。
標准C語言(ANSI C)共定義了15 個頭文件,稱為“C標准庫”,所有的編譯器都必須支持,如何正確並熟練的使用這些標准庫,可以反映出一個程序員的水平。
- 合格程序員:<stdio.h>、<ctype.h>、<stdlib.h>、<string.h>
- 熟練程序員:<assert.h>、<limits.h>、<stddef.h>、<time.h>
- 優秀程序員:<float.h>、<math.h>、<error.h>、<locale.h>、<setjmp.h>、<signal.h>、<stdarg.h>
是先掌握一些最基本、最常用的函數,在實踐過程中再逐步深入。根據需要查閱C語言函數手冊,網址是 http://www.cplusplus.com。