C語言學習四 — 函式與作用域規則
函式
函式是一組一起執行一個任務的語句。每個 C 程式都至少有一個函式,即主函式 main() ,所有簡單的程式都可以定義其他額外的函式。
您可以把程式碼劃分到不同的函式中。如何劃分程式碼到不同的函式中是由您來決定的,但在邏輯上,劃分通常是根據每個函式執行一個特定的任務來進行的。
函式宣告告訴編譯器函式的名稱、返回型別和引數。函式定義提供了函式的實際主體。
C 標準庫提供了大量的程式可以呼叫的內建函式。例如,函式 strcat() 用來連線兩個字串,函式 memcpy() 用來複制記憶體到另一個位置。
函式還有很多叫法,比如方法、子例程或程式,等等
定義函式
C 語言中的函式定義的一般形式如下:
return_type function_name( parameter list )
{
body of the function
}
在 C 語言中,函式由一個函式頭和一個函式主體組成。下面列出一個函式的所有組成部分:
返回型別:一個函式可以返回一個值。return_type 是函式返回的值的資料型別。有些函式執行所需的操作而不返回值,在這種情況下,return_type 是關鍵字 void。
函式名稱:這是函式的實際名稱。函式名和引數列表一起構成了函式簽名。
引數:引數就像是佔位符。當函式被呼叫時,您向引數傳遞一個值,這個值被稱為實際引數。引數列表包括函式引數的型別、順序、數量。引數是可選的,也就是說,函式可能不包含引數。
-
函式主體:函式主體包含一組定義函式執行任務的語句。
例項
以下是 max() 函式的原始碼。該函式有兩個引數 num1 和 num2,會返回這兩個數中較大的那個數:
int max_num(int num, int numT) { return num > numT ? num : numT; }
printf("max num is %d",max_num(5,9));
max num is 9
Process finished with exit code 0
函式宣告
函式宣告會告訴編譯器函式名稱及如何呼叫函式。函式的實際主體可以單獨定義。
函式宣告包括以下幾個部分:
return_type function_name( parameter list );
針對上面定義的函式 max(),以下是函式宣告:
int max(int num1, int num2);
在函式宣告中,引數的名稱並不重要,只有引數的型別是必需的,因此下面也是有效的宣告:
int max(int, int);
當您在一個原始檔中定義函式且在另一個檔案中呼叫函式時,函式宣告是必需的。在這種情況下,您應該在呼叫函式的檔案頂部宣告函式。
呼叫函式
建立 C 函式時,會定義函式做什麼,然後通過呼叫函式來完成已定義的任務。
當程式呼叫函式時,程式控制權會轉移給被呼叫的函式。被呼叫的函式執行已定義的任務,當函式的返回語句被執行時,或到達函式的結束括號時,會把程式控制權交還給主程式。
呼叫函式時,傳遞所需引數,如果函式返回一個值,則可以儲存返回值。例如:
#include <stdio.h>
/* 函式宣告 */
int max(int , int );
int main ()
{
/* 區域性變數定義 */
int a = 100;
int b = 200;
/* 呼叫函式來獲取最大值 */
int ret = max(a, b);
printf( "Max value is : %d\n", ret );
return 0;
}
/* 函式返回兩個數中較大的那個數 */
int max(int num, int numT)
{
return num > numT ? num : numT;
}
函式引數
如果函式要使用引數,則必須宣告接受引數值的變數。這些變數稱為函式的形式引數。
形式引數就像函式內的其他區域性變數,在進入函式時被建立,退出函式時被銷燬。
當呼叫函式時,有兩種向函式傳遞引數的方式:
呼叫型別 | 描述 |
---|---|
傳值呼叫 | 該方法把引數的實際值複製給函式的形式引數。在這種情況下,修改函式內的形式引數不會影響實際引數。 |
引用呼叫 | 通過指標傳遞方式,形參為指向實參地址的指標,當對形參的指向操作時,就相當於對實參本身進行的操作。 |
預設情況下,C 使用傳值呼叫來傳遞引數。一般來說,這意味著函式內的程式碼不能改變用於呼叫函式的實際引數。
傳值方式呼叫函式
向函式傳遞引數的傳值呼叫方法,把引數的實際值複製給函式的形式引數。在這種情況下,修改函式內的形式引數不會影響實際引數。
預設情況下,C 語言使用傳值呼叫方法來傳遞引數。一般來說,這意味著函式內的程式碼不會改變用於呼叫函式的實際引數。**函式 switch() 定義如下:
void switch_num(int a, int b) {
int temp;
temp = a;
a = b;
b = temp;
}
void print_switch() {
int a = 100, b = 200;
printf("before,a is : %d b is : %d\n", a, b);
/* 呼叫函式來交換值 */
switch_num(a, b);
printf("after,a is : %d b is : %d", a, b);
}
before,a is : 100 b is : 200
after,a is : 100 b is : 200
Process finished with exit code 0
引用方式呼叫函式
通過引用傳遞方式,形參為指向實參地址的指標,當對形參的指向操作時,就相當於對實參本身進行的操作。
傳遞指標可以讓多個函式訪問指標所引用的物件,而不用把物件宣告為全域性可訪問。
void switch_num(int *a, int *b) {
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void print_switch() {
int a = 100, b = 200;
printf("before,a is : %d b is : %d\n", a, b);
/* 呼叫函式來交換值
* &a 表示指向 a 的指標,即變數 a 的地址
* &b 表示指向 b 的指標,即變數 b 的地址
*/
switch_num(*a, *b);
printf("after,a is : %d b is : %d", a, b);
}
before,a is : 100 b is : 200
after,a is : 200 b is : 100
Process finished with exit code 0
作用域規則
任何一種程式設計中,作用域是程式中定義的變數所存在的區域,超過該區域變數就不能被訪問。C 語言中有三個地方可以宣告變數:
- 在函式或塊內部的區域性變數
- 在所有函式外部的全域性變數
- 在形式引數的函式引數定義中
讓我們來看看什麼是區域性變數、全域性變數和形式引數。
區域性變數
在某個函式或塊的內部宣告的變數稱為區域性變數。它們只能被該函式或該程式碼塊內部的語句使用。區域性變數在函式外部是不可知的。下面是使用區域性變數的例項。在這裡,所有的變數 a、b 和 c 是 main() 函式的區域性變數。
#include <stdio.h>
int main ()
{
/* 區域性變數宣告 */
int a, b;
int c;
/* 實際初始化 */
a = 10;
b = 20;
c = a + b;
printf ("value of a = %d, b = %d and c = %d\n", a, b, c);
return 0;
}
全域性變數
全域性變數是定義在函式外部,通常是在程式的頂部。全域性變數在整個程式生命週期內都是有效的,在任意的函式內部能訪問全域性變數。
全域性變數可以被任何函式訪問。也就是說,全域性變數在宣告後整個程式中都是可用的。下面是使用全域性變數和區域性變數的例項:
#include <stdio.h>
/* 全域性變數宣告 */
int g;
int main ()
{
/* 區域性變數宣告 */
int a, b;
/* 實際初始化 */
a = 10;
b = 20;
g = a + b;
printf ("value of a = %d, b = %d and g = %d\n", a, b, g);
return 0;
}
在程式中,區域性變數和全域性變數的名稱可以相同,但是在函式內,區域性變數的值會覆蓋全域性變數的值,但不會改變全域性變數的值。下面是一個例項:
#include <stdio.h>
/* 全域性變數宣告 */
int g = 20;
int main ()
{
/* 區域性變數宣告,此變數和全域性變數不是同一個 */
int g = 10;
printf ("value of g = %d\n", g);//離誰近,就優先列印誰
return 0;
}
形式引數
函式的引數,形式引數,被當作該函式內的區域性變數,它們不會覆蓋全域性變數。下面是一個例項:
#include <stdio.h>
/* 全域性變數宣告 */
int a = 20;
int main ()
{
/* 在主函式中的區域性變數宣告 */
int a = 10;
int b = 20;
int c = 0;
int sum(int, int);//未定義值,只是一個函式
printf ("value of a in main() = %d\n", a);
c = sum( a, b);
printf ("value of c in main() = %d\n", c);
return 0;
}
/* 新增兩個整數的函式 */
int sum(int a, int b)
{
printf ("value of a in sum() = %d\n", a);
printf ("value of b in sum() = %d\n", b);
return a + b;
}
value of a in main() = 10
value of a in sum() = 10
value of b in sum() = 20
value of c in main() = 30
C 的形參與實參
在 C 語言中,形參與實參雖然很簡單,但是,是大家比較容易混淆的一個點,這裡將為大家詳細的講解。
概念:從字面上理解,所謂形式引數即只只是宣告瞭一個作為引數的變數,並未直接進行賦值使用,而實際引數則相反。
如下例
#include <stdio.h>
int test(int,int); // 形參,只宣告
int main()
{
int a,b;
printf("%d",test(5,3)); // 實參,已賦值
}
int test(int a,int b) // 形參
{
a=a+b;
return a;
}
像上面在 test() 函式裡只宣告瞭最為引數的變數,而 main() 函式裡則對它賦了值。
初始化區域性變數和全域性變數
當區域性變數被定義時,系統不會對其初始化,您必須自行對其初始化。定義全域性變數時,系統會自動對其初始化,如下所示:
資料型別 | 初始化預設值 |
---|---|
int | 0 |
char | '\0' |
float | 0 |
double | 0 |
pointer | NULL |
正確地初始化變數是一個良好的程式設計習慣,否則有時候程式可能會產生意想不到的結果,因為未初始化的變數會導致一些在記憶體位置中已經可用的垃圾值。
相關文章
- c語言學習筆記===函式C語言筆記函式
- 函式與作用域函式
- Linux C語言高階學習第四天(C高階-函式)LinuxC語言函式
- C語言學習之認識exit()函式C語言函式
- c語言學習--time庫函式詳解C語言函式
- go語言學習-函式Go函式
- C語言函式手冊:c語言庫函式大全|C語言標準函式庫|c語言常用函式查詢C語言函式
- 【Go語言學習】匿名函式與閉包Go函式
- 函式 -- 就要學習 Go 語言函式Go
- C語言函式指標與回撥用函式C語言函式指標
- 函數語言程式設計3-作用域與閉包函數程式設計
- 從開源專案學習 C 語言基本的編碼規則
- C++學習筆記-C++對C語言的函式擴充C++筆記C語言函式
- Solidity語言學習筆記————25、作用域和宣告Solid筆記
- C語言 execve()函式C語言函式
- C語言常用函式C語言函式
- C語言的函式C語言函式
- 函式(三)作用域之變數作用域、函式巢狀中區域性函式作用域、預設值引數作用域函式變數巢狀
- 第 8 節:函式-函式型別與作用域函式型別
- C語言學習方法,怎麼學習C語言?C語言
- 函式學習四函式
- 小白學習Golang(六)Go語言函式Golang函式
- PostgreSQL學習手冊(SQL語言函式)SQL函式
- JS內建物件,函式與作用域JS物件函式
- C語言 itoa函式及atoi函式C語言函式
- C語言函式指標與回撥函式使用方法C語言函式指標
- C語言函式呼叫棧C語言函式
- 詳解C語言函式C語言函式
- tmpnam() - C語言庫函式C語言函式
- tmpfile() - C語言庫函式C語言函式
- C語言時間函式C語言函式
- c語言函式庫(轉)C語言函式
- C語言 函式指標C語言函式指標
- 08. C語言函式C語言函式
- C語言基礎函式C語言函式
- e語言 類似eval函式作用的函式
- C++程式語言的四個準則C++
- Erlang學習筆記(四)模組與函式筆記函式