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