c語言的引數
函式的引數—實參|形參
在函式定義中出現的引數可以看做是一個佔位符,它沒有資料,只能等到函式被呼叫時接收傳遞進來的資料,所以稱為形式引數,簡稱形參。
函式被呼叫時給出的引數包含了實實在在的資料,會被函式內部的程式碼使用,所以稱為實際引數,簡稱實參。
形參和實參的功能是傳遞資料,發生函式呼叫時,實參的值會傳遞給形參。
形參和實參有以下幾個特點:
1) 形參變數只有在函式被呼叫時才會分配記憶體,呼叫結束後,立刻釋放記憶體,所以形參變數只有在函式內部有效,不能在函式外部使用。
2) 實參可以是常量、變數、表示式、函式等,無論實參是何種型別的資料,在進行函式呼叫時,它們都必須有確定的值,以便把這些值傳送給形參,所以應該提前用賦值、輸入等辦法使實參獲得確定值。
3) 實參和形參在數量上、型別上、順序上必須嚴格一致,否則會發生“型別不匹配”的錯誤。當然,如果能夠進行自動型別轉換,或者進行了強制型別轉換,那麼實參型別也可以不同於形參型別。
4) 函式呼叫中發生的資料傳遞是單向的,只能把實參的值傳遞給形參,而不能把形參的值反向地傳遞給實參;換句話說,一旦完成資料的傳遞,實參和形參就再也沒有瓜葛了,所以,在函式呼叫過程中,形參的值發生改變並不會影響實參。
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。
3) C語言規定,只能從小的作用域向大的作用域中去尋找變數,而不能反過來,使用更小的作用域中的變數。對於 main() 函式,即使程式碼塊中的 n 離輸出語句更近,但它仍然會使用 main() 函式開頭定義的 n,所以輸出結果是 30。