文章目錄
- 1. 前言
- 2. 函數的概念
- 3.庫函數
- 3.1 標準庫和頭文件
- 3.2 庫函數的使用
- 3.2.1 頭文件的包含
- 3.2.2 實踐
- 4. 自定義函數
- 4.1 自定義函數的語法形式
- 4.2 函數的舉例
- 5. 形參和實參
- 5.1 實參
- 5.2 形參
- 5.3 實參和形參的關系
- 6. return 語句
- 6. 總結
1. 前言
一講到函數這塊,相信有很多初學者都避而不及。開個玩笑說,你是否聽到函數身體就止不住的顫抖,冷汗直流,必須得來幾瓶匯源腎寶才能勉強繼續學下去。😰😰😰
不過沒關系,相信你看完這個文章之后不會再懼怕函數,甚至可能會愛上使用它。
那么話不多說,讓我們一起去揭開函數這個神秘的面紗吧!😎😎??
2. 函數的概念
古人有云:知己知彼,才能百戰不殆。學習也是如此,當我們面對一個新的知識時,我們得先對這個新事物有個整體的認知,在此基礎上繼續挖掘更深層次的知識,就事半功倍了。
一說到函數,相信大家就想到了初中那段剛接觸到函數的時光,你是否被它折磨的痛不欲生了呢?不過沒有關系,本文會帶你駛向勝利的彼岸。比如:一次函數y=kx+b 、二次函數y=ax2+bx+c,根據函數的映射關系,我們就可以根據自變量(x)的值從而求得因變量(y)。
其實在C語言中也引入了函數(function)這一概念,有些地方也將它翻譯成:子程序,我認為子程序的翻譯更加準確一些。也就是說,函數其實就是一段子程序。
那可能有的讀者就會問了,子程序是什么,難道還會有個母函數?
所謂的子程序就是,總的項目程序代碼中的一部分,它能夠完成某一項特定的任務,并且這段代碼有特許的寫法和調用方式。 當然,目前你可以簡單的理解為程序代碼的一部分。相信你看文本后,再回頭思考這個問題時,就會有很深的感悟了。
既然講到了C語言程序這個概念,就再跟大家聊聊什么是程序?
- 從目的角度理解的話,程序就是程序為了實現某種目的作用于現實生活而編程出來的可執行文件。
- 從程序本身來理解的話,程序就是由無數個小的函數組合而成,也可以說:一個大的計算任務可以分解成若干個較小的函數(每個函數都對應這一個小的任務)完成。同時一個函數如果能完成某一項特定任務的話,那么這個也是可以重復被使用了,程序員就無需打那么多重復的代碼,大大提高了編程的效率。
在C語言中我們一般會見到兩類函數:
- 庫函數
- 自定義函數
在這里我們先從較為簡單庫函數講起。
3.庫函數
說到庫函數,一定就離不開C語言中的標準庫和頭文件。
3.1 標準庫和頭文件
C語言標準中規定了C語言的各種語法規則,C語言本身并不提供庫函數,C語?的國際標準ANSI C規定了?些常?的函數的標準,被稱為標準庫。C語言那到底是誰給我們提供呢?制作編譯器的廠商們。這些廠商們拿著ANSI提供的C語言標準制定了一系列函數的實現。這些函數就被稱為庫函數。
總而言之,標準庫就是一個國際組織制定的標準,在里面存放著編譯器廠商是實現的庫函數。
其實,我們在日常編程中幾乎都用到了庫函數,比如printf
、scanf
這些都是庫函數,庫函數也是函數,只不過是別人已經幫我們實現好了,我們只需要直接拿出來用就行了。
各種編譯器的標準庫提供了一系列的庫函數,這些庫函數根據功能的劃分,都在不同的頭文件中進行了聲明(也就是說,我們在使用這些庫函數時,得先包含對應的頭文件)。
庫函數相關頭文件鏈接:https://zh.cppreference.com/w/c/header
里面的函數多種多樣,不需要大家一次性學完,等需要用到的時候,再去查就可以了。
3.2 庫函數的使用
庫函數的學習和查找工具有很多,以下是我推薦給大家的:
C/C++官?的鏈接:https://zh.cppreference.com/w/c/header
cplusplus.com:https://cplusplus.com/
舉例:sqrt
double sqrt(double x);
//sqrt是函數名
//x 是函數的參數,表示調用sqrt函數時需要傳遞一個double類型的值
//double 是返回值類型 —— 表示函數計算的結果是一個double類型的值
以下截圖是來自:cplusplus網站
3.2.1 頭文件的包含
在前面我有提及過,在我們使用庫函數,要先包含一個頭文件。因為庫函數是在標準庫中對應的頭文件中聲明的,所以使用庫函數時請務必包含頭文件。
這就好比,你去借別人的東西,不包含頭文件的情況,就比做你直接就拿別人的東西去用了,也沒詢問過別人的意見,這個就是一個很沒有禮貌的行為。而包含了頭文件之后,就比做你已經再征得別人的同意后才使用的,這就是一個有禮貌行為的體現。
3.2.2 實踐
講了這么多了,是時候動手寫個代碼,給大家展示一下用法:
#include<stdio.h>
#include<math.h> //sqrt函數被聲明在這個頭文件里,得先打聲招呼int main()
{double x = 16.0;double r = sqrt(x);printf("%lf\n",r);return 0;
}
大家下來可以自己測試一下結果!
4. 自定義函數
了解了庫函數之后,我們的關注度應該放在自定義函數上,自定義函數其實更加重要,也能給程序員寫代碼更多的創造性。
4.1 自定義函數的語法形式
其實自定義函數和庫函數一樣,形式如下:
ret_num fun_name(形式參數)
{...
}
名稱 | 意義 |
---|---|
ret_num | 是函數的返回值類型 |
fun_name | 是函數名 |
()里面放的內容 | 是形式參數 |
{…}括里面的內容 | 是函數體(函數的主要內容) |
我們可以把函數想象成一座小型的工廠,工廠通過輸入進來的原材料,經過加工才能身邊生產出產品。那函數也是一樣的,函數一般會給它輸入一些值(可以是0個,也可以是多個),經過函數內部的計算,得出最終的計算結果。
為此,我再次寫一下,函數創建語法時,各個英文單詞所代表的具體含義。請大家對照著理解,
ret_type
是?來表?函數計算結果的類型,有時候返回類型可以是 void ,表?什么都不返回fun_name
是為了?便使?函數;就像?的名字?樣,有了名字?便稱呼,函數有了名字?便調?,所以函數名盡量要根據函數的功能起的有意義。- 函數的參數就相當于,工廠中送進去的原材料,函數的參數也可以是 void ,明確表?函數沒有參數。如果有參數,要交代清楚參數的類型和名字,以及參數個數。
- {}括起來的部分被稱為函數體,函數體就是完成計算的過程。
4.2 函數的舉例
舉個例子:
寫一個加法函數,完成對兩個整型變量的加法操作。
在我們沒學過函數之前,你可能會這么寫:
#include<stdio.h>
int main()
{int a = 0;int b = 0;scanf("%d %d",&a,&b);int ret = a + b;printf("ret = %d\n", ret);return 0;
}
這是你學過函數之后寫的代碼:
#include<stdio.h>
int Add(int x, int y) //x,y就是形式參數
{int sum = 0;sum = x + y;return sum;
}int main()
{int a = 0;int b = 0;scanf("%d %d",&a,&b);int ret = Add(a, b);printf("ret = %d\n", ret);return 0;
}
不過上述的Add函數的寫法還可以再簡化
int Add(int x, int y)
{return x + y;
}
上?只是?個例?,未來我們是根據實際需要來設計函數,函數名、參數、返回類型都是可以靈活變化的。
5. 形參和實參
在函數的使用過程中,把函數的參數分為,實參和形參。
在看看我們之前舉例的代碼:
#include<stdio.h>
int Add(int x, int y) //x,y就是形式參數
{int sum = 0;sum = x + y;return sum;
}int main()
{int a = 0;int b = 0;scanf("%d %d",&a,&b);int ret = Add(a, b);printf("ret = %d\n", ret);return 0;
}
5.1 實參
在上面代碼中第2~7行是Add函數的定義,有了函數之后,再調用第14行的Add函數。
我們把調用Add函數時,傳遞給Add函數的參數a和b,稱為實際參數,簡稱實參。
實際參數就是真實給函數傳遞的值。
可以理解為實參就是給這個函數的原材料。
或者,我再舉一個生動的例子。就比如說,我們的手機沒電時,需要充電,第一步就是將充電器插入到電插座中,第二步就是將充電頭插入自己手機的充電口中。這兩步的插入目的就是給手機充電,就好比我們給函數傳遞實參一樣。函數需要這么一個介質,才能發揮出它應有的功能。
5.2 形參
在上面代碼中,第二行定義函數時,在函數名Add后的括號中寫的x和y,稱為形式參數,簡稱形參。
為什么會叫形式參數呢?實際上,如何只是定義了Add函數而不去調用的話,Add函數的參數x和y只是形式上存在的,它們是不會向內存申請空間的,不會真實存在的,所以叫形式參數。形式參數只有在函數被調用的過程中,才會向內存中申請空間,這個過程就叫做形式參數的實例化。
5.3 實參和形參的關系
形式參數和實際參數,它們的名字中都有參數二字,那它們中間有什么關系嗎?
請大家務必記住這句話:
形參是實參的一份臨時拷貝
為什么這么說呢?
下面我就通過調試辦法來觀察參數的變化:
在調試的時候,我們發現x和y的確是得到了a和b的值,但是x和y的地址與a和b的地址是不一樣的,所以我們就可以理解為形參是實參的一份臨時拷貝。
6. return 語句
return作為C語言中的關鍵字,在自定義函數中時常出現,這里就講一下return語句使用的注意事項:
- return后面可以是個數值,也可以是個表達式,如果是表達式則先執行表達式,再返回表達式的結果。
- return后邊也可以什么都沒有,直接寫
return;
這種寫法適合函數返回值類型是void的情況。 - return返回的值和函數返回值的類型不一致,系統會自動將返回的值隱式轉換為函數的返回類型。
- return語句執行后,函數就徹底返回了,后邊的代碼就不再執行了。
- 如果函數中存在
if
等分支語句時,則要保證每種情況下都有return返回,否則就會出現編譯錯誤。
為了方便大家的理解,我會給出幾段代碼,分別說明一下,遵守這些規則的好處以及不遵守這些規則所帶來一些意想不到的"效果":
注意事項1:return后面可以是個數值,也可以是個表達式,如果是表達式則先執行表達式,再返回表達式的結果。
//我們可以這樣寫
int Add(int x, int y)
{return x+y; //這個return語句后面是一個表達式
}int main()
{int a = 0;int b = 0;scanf("%d %d",&a,&b);int ret = Add(a, b);printf("ret = %d\n", ret);return 0;
}
注意事項2:return后邊也可以什么都沒有,直接寫return;
這種寫法適合函數返回值類型是void的情況。
void Print()
{printf("***********\n");printf("***********\n");printf("***********\n");printf("***********\n");return;//這個其實可寫可不寫
}int main()
{Print();return 0;
}
注意事項3:return返回的值和函數返回值的類型不一致,系統會自動將返回的值隱式轉換為函數的返回類型。
這里編譯器會報出個警告:
但是我們這樣改進的話就不會出現了:
注意事項4/5:return語句執行后,函數就徹底返回了,后邊的代碼就不再執行了。
可以看到hehehehe并沒有被打印處理來,也就說明了,當函數體執行到return語句之后,后面的語句就不再被執行。
6. 總結
本文講解了什么是標準庫、庫函數,以及介紹了函數的定義,函數的調用。還仔細地剖析了自定義函數的語法,形式參數和實際參數及其它們之間的關系,return語句。
本章內容有點豐富,希望讀者們下來好好理解。🥇????
學習很難,但堅持一定很酷!!!😎😎😎