C语言中的函数(详解)
目錄
1.函數(shù)是什么
2.c語言中函數(shù)的分類:
2.1. 庫函數(shù)
2. 自定義函數(shù)
3. 函數(shù)的參數(shù)
3.1 實(shí)際參數(shù)(實(shí)參)
3.2 形式參數(shù)(形參)
4. 函數(shù)的調(diào)用:
4.1 傳值調(diào)用
4.2 傳址調(diào)用
5. 函數(shù)的嵌套調(diào)用和鏈?zhǔn)皆L問?
5.1 嵌套調(diào)用?
5.2 鏈?zhǔn)皆L問
6.函數(shù)的聲明和定義
6.1 函數(shù)聲明:
6.2 函數(shù)定義:
7. 函數(shù)遞歸
7.1 什么是遞歸??
7.2 遞歸的兩個必要條件?
1.函數(shù)是什么
在維基百科中,對于函數(shù)的定義是子程序。子程序是一個大型程序中的某部分代碼,由一個或多個語句塊組成,他負(fù)責(zé)完成某項特定的任務(wù),而且相較于其他的代碼,具備相對的獨(dú)立性。
一般會有輸入參數(shù)并有返回值,提供對過程的封裝和細(xì)節(jié)的隱藏。這些代碼通常被集成為軟
件庫。
2.c語言中函數(shù)的分類:
2.1. 庫函數(shù)
為什么會有庫函數(shù)呢?
早期的c語言是沒有函數(shù)的,他只規(guī)定你語法,比如for循環(huán)之類的該怎么寫然后各種各樣的語法細(xì)節(jié)的規(guī)則非常規(guī)定的很清楚,就是你寫出的代碼能夠編輯處理。但是當(dāng)有一天呢,A想在屏幕上打印一個信息的時候A就實(shí)現(xiàn)了一個類似于printf1的函數(shù)的功能。那這個時候呢,B說,我也要一個打印的函數(shù),于是他寫了一個printf2,后來c說,他也想打印。那他呢,也寫了一個printf3函數(shù)。
這些人都互相都不知道,所以我們看一下。當(dāng)我們每個人都去實(shí)行打印這個功能的時候,這個代碼時,就變得冗余了。
第二是什么呢?開發(fā)效率低,我們每個人都在重復(fù)的造論子,你寫一個,他也寫一個,別人再寫一個。寫的都是類似的功能,開發(fā)效率當(dāng)然低了。
第三個就是不標(biāo)準(zhǔn),你寫的他寫的都是同一功能,但是這個實(shí)現(xiàn)方法可能不一樣。參數(shù)也可能不一樣,返回值類型也可能不一樣。
所以基于以上原因。 那能不能把常用的一些功能實(shí)現(xiàn)成函數(shù)呢?那這個時候呢,就有了庫函數(shù)的概念,這個函數(shù)只要把參數(shù)規(guī)定死了。 返回類型規(guī)定死了。函數(shù)名規(guī)定死了,那他的使用方法肯定就是一模一樣了,庫函數(shù)的出現(xiàn)讓我們代碼的其實(shí)開發(fā)效率的變高了。 代碼的更加標(biāo)準(zhǔn)化了。
注:但是庫函數(shù)的使用必須包含對應(yīng)的頭文件
這里有兩個推薦學(xué)習(xí)的網(wǎng)站:cppreference.com
cplusplus.com - The C++ Resources Network
那怎么學(xué)習(xí)庫函數(shù)呢?
這里我們簡單的看看:http://www.cplusplus.com
這是c的庫,我們在左邊的部分可以很快的找到我們曾經(jīng)用過的函數(shù),那么我將用一個例子帶著你來學(xué)習(xí)庫函數(shù)。?
strcpy這個函數(shù)包含在string.h這個頭文件里面,這個函數(shù)的參數(shù)需要兩個指針,返回值是一個字符型指針,指針就是地址,char * strcpy ( char * destination, const char * source );
Copies the C string pointed by?source?into the array pointed by?destination, including the terminating null character (and stopping at that point).
翻譯過來就是將source指向的C字符串復(fù)制到destination指向的數(shù)組中,包括終止的空字符(并在該點(diǎn)停止)。包括'\0'字符。
Pointer to the destination array where the content is to be copied.
指向目標(biāo)數(shù)組的指針,那兒目標(biāo)數(shù)組的內(nèi)容要被復(fù)制。
C string to be copied.
要被復(fù)制的c字符串
?返回值是destiination,destiination是一個字符型指針。
總結(jié)一句話,就是strcpy函數(shù)是將一個字符串復(fù)制到另一個字符串上去的。
2. 自定義函數(shù)
如果庫函數(shù)能干所有的事情,那還要程序員干什么?所以更加重要的是自定義函數(shù)。自定義函數(shù)和庫函數(shù)一樣,有函數(shù)名,返回值類型和函數(shù)參數(shù)。但是不一樣的是這些都是我們自己來設(shè)計。這給程序員一個很大的發(fā)揮空間。
函數(shù)的組成:
ret_type fun_name(para1, * )
{
statement;//語句項
}
ret_type 返回類型
fun_name 函數(shù)名
para1 ??函數(shù)參數(shù)
給個例子,一看便知。
3. 函數(shù)的參數(shù)
3.1 實(shí)際參數(shù)(實(shí)參)
真實(shí)傳給函數(shù)的參數(shù),叫實(shí)參。實(shí)參可以是:常量、變量、表達(dá)式、函數(shù)等。無論實(shí)參是何種類型的量,在進(jìn)行函數(shù)調(diào)用時,它們都必須有確定的值,以便把這些值傳送給形參。
3.2 形式參數(shù)(形參)
形式參數(shù)是指函數(shù)名后括號中的變量,因?yàn)樾问絽?shù)只有在函數(shù)被調(diào)用的過程中才實(shí)例化(分配內(nèi)
存單元),所以叫形式參數(shù)。形式參數(shù)當(dāng)函數(shù)調(diào)用完成之后就自動銷毀了。因此形式參數(shù)只在函數(shù)中有效。
形參和實(shí)參的名字可以一樣,不影響什么。
4. 函數(shù)的調(diào)用:
4.1 傳值調(diào)用
函數(shù)的形參和實(shí)參分別占有不同內(nèi)存塊,對形參的修改不會影響實(shí)參。
寫一個函數(shù)可以交換兩個整形變量的內(nèi)容?
void swap(int p1, int p2) {int tmp = 0;tmp = p1;p1 = p2;p2 = tmp; } int main() {int a = 0;int b = 0;scanf("%d%d", &a, &b);printf("交換前,a = %d b = %d\n", a, b);swap(a, b);/*int p1 = &a;int p2 = &b;swap(p1, p2);*/printf("交換后,a = %d b = %d\n", a, b);return 0; }可以看出,我明明把參數(shù)傳進(jìn)去了,為什么參數(shù)卻還沒有交換呢?我們要用到重要的傳址調(diào)用了。
4.2 傳址調(diào)用
傳址調(diào)用是把函數(shù)外部創(chuàng)建變量的內(nèi)存地址傳遞給函數(shù)參數(shù)的一種調(diào)用函數(shù)的方式。這種傳參方式可以讓函數(shù)和函數(shù)外邊的變量建立起真正的聯(lián)系,也就是函數(shù)內(nèi)部可以直接操作函數(shù)外部的變量。
void swap(int* p1 , int* p2) {int tmp = 0;tmp = *p1;*p1 = *p2;*p2 = tmp; } int main() {int a = 0;int b = 0;scanf("%d%d", &a, &b);printf("交換前,a = %d b = %d\n", a, b);swap(&a, &b);/*int p1 = &a;int p2 = &b;swap(p1, p2);*/printf("交換后,a = %d b = %d\n", a, b);return 0; }實(shí)參中,我將a,b的地址給傳了進(jìn)去,形參又用p1和p2兩個指針存儲了a,b的地址,接著用 * 操作符找到了a,b的地址并修改了里面的內(nèi)容。
5. 函數(shù)的嵌套調(diào)用和鏈?zhǔn)皆L問?
5.1 嵌套調(diào)用?
#include <stdio.h> void new_line() {printf("hehe\n"); } void three_line() {int i = 0;for (i = 0; i < 3; i++){new_line();} } int main() {three_line();return 0; } int main() {void test(){//......}return 0; }?這種就是嵌套定義,即在一個函數(shù)內(nèi)部去定義函數(shù),是不可以的。
函數(shù)可以嵌套調(diào)用,但是不能嵌套定義。
5.2 鏈?zhǔn)皆L問
把一個函數(shù)的返回值作為另外一個函數(shù)的參數(shù)。
這個為什么打印的是4321呢?我們要查一下printf的返回值。所以結(jié)果是4321也就不足為奇了。
6.函數(shù)的聲明和定義
6.1 函數(shù)聲明:
?程序在執(zhí)行的時候是一步一步往下走的,下面這張圖則是教科書上的寫法,我們調(diào)用一個函數(shù)時,要有函數(shù)的聲明,可如果函數(shù)寫在了main函數(shù)的上方,則不余需要聲明了。
?1. 告訴編譯器有一個函數(shù)叫什么,參數(shù)是什么,返回類型是什么。但是具體是不是存在,函數(shù)
? ? 聲明決定不了。
2. 函數(shù)的聲明一般出現(xiàn)在函數(shù)的使用之前。要滿足先聲明后使用。
3. 函數(shù)的聲明一般要放在頭文件中的。
6.2 函數(shù)定義:
函數(shù)的定義是指函數(shù)的具體實(shí)現(xiàn),交待函數(shù)的功能實(shí)現(xiàn)。?
6.3 工作中的寫法?
我們是會把Add函數(shù)寫成一個加法模塊。在主函數(shù)中調(diào)用Add的頭文件即可。各自分開寫代碼,會讓邏輯變得很清晰。
?
?
?
那么為什么要把源文件和頭文件分開呢?假如你是一個程序員,你只想別人使用你寫的模塊。但是卻不想讓別人怎么看你實(shí)現(xiàn)的,只是告訴他怎么使用,這個時候你可以將 .c 文件設(shè)置成靜態(tài)庫。也就是把函數(shù)聲明給出去,函數(shù)怎么實(shí)現(xiàn)的隱藏起來。
接下來教你怎么操作。我們先將上面的add.h add.c 文件從項目中移除。
然后關(guān)閉當(dāng)前的解決方案,新建一個add項目,再打開之前關(guān)閉的解決方案文件所在的位置,將add.h add.c剪切到add文件里面。
?
?
?如果,不愿意暴露代碼。可以編譯成靜態(tài)庫。
?
?用記事本打開add.lib文件,會發(fā)現(xiàn)全是亂的。?
?然后將add.lib文件 和 add.h文件都放到我們最初的解決方案的文件里面?
?
將add.h添加到test.c中,#pragma comment(lib,"add.lib") 導(dǎo)入靜態(tài)庫的意思。?
?
這樣,我們就完成了。?這樣做的好處,是可以將一些核心代碼隱藏起來。?
其實(shí),c語言中的庫函數(shù),你直接包含頭文件就可以使用,但實(shí)際上你也是看不到這些庫函數(shù)是怎么實(shí)現(xiàn)的,之所以是能直接使用,是vs這個編譯器默認(rèn)將這些庫函數(shù)的靜態(tài)庫導(dǎo)入了。
7. 函數(shù)遞歸
7.1 什么是遞歸??
程序調(diào)用自身的編程技巧稱為遞歸( recursion)。遞歸做為一種算法在程序設(shè)計語言中廣泛應(yīng)用。 一個過程或函數(shù)在其定義或說明中有直接或間接調(diào)用自身的一種方法,它通常把一個大型復(fù)雜的問題層層轉(zhuǎn)化為一個與原問題相似的規(guī)模較小的問題來求解,遞歸策略只需少量的程序就可描述出解題過程所需要的多次重復(fù)計算,大大地減少了程序的代碼量。遞歸的主要思考方式在于:把大事化小
7.2 遞歸的兩個必要條件?
存在限制條件,當(dāng)滿足這個限制條件的時候,遞歸便不再繼續(xù)。
每次遞歸調(diào)用之后越來越接近這個限制條件
我會在下一篇詳細(xì)講解遞歸的一些題目,希望各位看官點(diǎn)點(diǎn)贊吧?!
總結(jié)
以上是生活随笔為你收集整理的C语言中的函数(详解)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 第二季3:海思MPP模块与视频缓冲池
- 下一篇: Unity联网插件(PUN)