摘要:可分為兩類,一類是語言標準規定的庫函數,一類是編譯器特定的庫函數。函數的調用傳值調用函數的形參和實參分別占有不同內存塊,對形參的修改不會影響實參。函數的聲明一般出現在函數的使用之前。函數的聲明一般要放在頭文件中的。
在維基百科中,對C語言中函數的定義是:子程序。
那么什么是子程序呢?
1、在計算機科學中,子程序(英語:Subroutine, procedure, function, routine, method,subprogram, callable unit),是一個大型程序中的某部分代碼,由一個或多個語句塊組成。它負責完成某項特定任務,而且相較于其他代 碼,具備相對的獨立性。
2、一般會有輸入參數并有返回值,提供對過程的封裝和細節的隱藏。這些代碼通常被集成為軟件庫。
從中提取信息點,“大型程序中的某部分代碼” “負責完成某項特定任務” 。舉個例子說,就比如我們在做計算器的時候,需要加減乘除四個大塊內容,我們在這里就可將加法做成一個多帶帶的代碼塊,專門用來實現加法的功能。這功能就是函數。
庫函數(Library function)是把函數放到庫里,供別人使用的一種方式。是把一些常用到的函數編完放到一個文件里,供不同的人進行調用。調用的時候把它所在的文件名用#include<>加到里面就可以了。一般是放到lib文件里的。
一般是指編譯器提供的可在c源程序中調用的函數。
可分為兩類,一類是c語言標準規定的庫函數,一類是編譯器特定的庫函數。
由于版權原因,庫函數的源代碼一般是不可見的,但在頭文件中你可以看到它對外的接口。
舉個例子:
像上面我們描述的基礎功能,它們不是業務性的代碼。我們在開發的過程中每個程序員都可能用的到,為了支持可移植性和提高程序的效率,所以C語言的基礎庫中提供了一系列類似的庫函數,方便程序員 進行軟件開發。
在這里,我們可以用到一個程序員必備網站:http://www.cplusplus.com/
打開,我們可以看到有非常多的庫函數
我們在這里以strcpy為例來給大家講解一下如何使用這個網站。
第一步,打開網站
第二步,搜索函數strcpy
第三步,查看函數功能與用法。
例子代碼:
#include #include int main(){ char arr1[20] = { 0 }; char arr2[] = "gogogo"; strcpy(arr1, arr2); printf("%s/n", arr1);}
相信通過這樣的講述,大家也能明白怎樣使用庫函數了吧!
在這里,簡單的總結,C語言常用的庫函數都有:
IO函數——輸入輸出函數 input/output printf scanf getchar putchar
字符串操作函數 strlen strcmp strcpy strcat
字符操作函數 tolower toupper
內存操作函數 memcpy menset memmove memcmp
時間日期函數 time
數學函數 sqrt abs fabs pow
其他庫函數
注意:
但是庫函數必須知道的一個秘密就是:使用庫函數,必須包含 #include 對應的頭文件。
需要學會查詢工具的使用:
MSDN(Microsoft Developer Network)
www.cplusplus.com
http://en.cppreference.com(英文版) http://ch.cppreference.com(中文版)
大家有沒有發現,庫函數并不能解決所有的問題,比如說我今天要寫一個自動刷牙的程序,可能庫函數中根本就沒有。這時候,就需要我們程序員自己來定義函數了
這就是自定義函數。
自定義函數和庫函數一樣,有函數名,返回值類型和函數參數。
但是不一樣的是這些都是我們自己來設計。這給程序員一個很大的自由發揮的空間。
ret_type fun_name(para1, * )
{
statement;//語句項
}ret_type 返回類型
fun_name 函數名
para1 函數參數
舉個例子:
寫一個函數找出兩個整數中的最大值
#include //get_max函數的設計int get_max(int x, int y) { return (x>y)?(x):(y);}int main(){ int num1 = 10; int num2 = 20; int max = get_max(num1, num2);//調用函數 printf("max = %d/n", max); return 0; }
在調用有參函數時,主調函數和被調函數之間有數據傳遞關系。
在主調函數中調用一個函數時,函數名后面括號中的參數稱為“實際參數”(簡稱“實參”)。
實參可以是常量、變量或表達式, 無論實參是何種類型的量,在進行函數調用時,它們都必須具有確定的值, 以便把這些值傳送給形參。 因此應預先用賦值,輸入等辦法使實參獲得確定值。
舉個例子:
#include void Swap1(int x, int y) { int tmp = 0; tmp = x; x = y; y = tmp; }void Swap2(int *px, int *py) { int tmp = 0; tmp = *px; *px = *py; *py = tmp; }int main(){ int num1 = 1; int num2 = 2; Swap1(num1, num2);//實參可以是常量、變量或表達式 printf("Swap1::num1 = %d num2 = %d/n", num1, num2); Swap2(&num1, &num2);//實參可以是常量、變量或表達式 printf("Swap2::num1 = %d num2 = %d/n", num1, num2); return 0; }
形式參數是指函數名后括號中的變量,因為形式參數只有在函數被調用的過程中才實例化(分配內存單元),所以叫形式參數。
形式參數當函數調用完成之后就自動銷毀了。因此形式參數只在函數中有效。
上面Swap1和Swap2函數中的參數 x,y,px,py 都是形式參數。
在main函數中傳給Swap1的num1,num2和傳給Swap2函數的&num1,&num2是實際參數。
這里我們對函數的實參和形參進行分析
借用網上的一幅圖
實參是調用函數傳遞的具體數據。實參對形參數據傳遞時時單向傳遞。在存儲單元中是不同的單元.
在上面的Swap1函數,在調用過程中,形參x和y的值都發生了改變,但是在main函數中,num1和num2的值都未發生變化。所以說實參向形參的值的傳遞是單向的。
Swap2函數,由于把地址也傳過去了,所以兩個值都改變了,這也是下面所講的傳值調用與傳址調用。
**【注意】**形參實例化之后其實相當于實參的一份臨時拷貝。
函數的形參和實參分別占有不同內存塊,對形參的修改不會影響實參。
舉個例子,交換兩個整數的值。
#include int Swap(int x, int y)//這里形參x,y占據的內存塊與下面實參a,b占據的內存塊是不同的{ int z = 0; z= x; x= y; y = z;}int main(){ int a = 10; int b = 20; printf("交換前a=%d,b=%d/n", a, b); Swap(a, b);//這里實參a,b占據的內存塊與上面形參x,y占據的內存塊是不同的 printf("交換后a=%d,b=%d/n", a, b); return 0;}
我們可以看到,這里a與b的值并沒有發生變化,因為**函數的形參和實參分別占有不同內存塊,對形參的修改不會影響實參。**所以,實參a和b,傳給形參x,y的時候,形參是實參的一份臨時拷貝,改變形參變量x,y,是不會影響實參a和b.
1、傳址調用是把函數外部創建變量的內存地址傳遞給函數參數的一種調用函數的方式。
2、這種傳參方式可以讓函數和函數外邊的變量建立起真正的聯系,也就是函數內部可以直接操作函數外部的變量。
舉個例子,也交換兩個整數的值
#include void Swap(int *px, int *py)//用指針接收a,b的地址{ int z = 0; z = *px; *px = *py; *py = z;}int main(){ int a = 10; int b = 20; printf("交換前a=%d,b=%d/n", a, b); Swap(&a,&b);//把a,b的地址傳到上面函數去 printf("交換后a=%d,b=%d/n", a, b); return 0;}
在這里,我們可以了解到,如果把a和b的內存地址傳過去給函數的時候,在函數中,我們就可以依照這個指針地址,傳數據回來。讓函數和函數外邊的變量建立起真正的聯系,也就是函數內部可以直接操作函數外部的變量。
需要說明的是,C語言中不允許作嵌套的函數定義。因此各函數之間是平行的,不存在上一級函數和下一級函數的問題。但是C語言允許在一個函數的定義中出現對另一個函數的調用。這樣就出現了函數的嵌套調用。即在被調函數中又調用其它函數。
舉個例子:
void first_line(){ printf("hello world/n");}void two_line(){ int i = 0; first_line();}int main(){ two_line(); return 0;}
main函數調用了two_line函數,而two_line函數調用了first_line函數。函數調用了函數,我們就說是函數的嵌套調用
**注意,**函數可以嵌套調用,但是不能嵌套定義。
什么意思?
就是說,我們不能在函數之中定義一個函數,舉個例子:
把一個函數的返回值作為另外一個函數的參數。
我們舉個例子。
#include int main(){ printf("%d/n", printf("%d", printf("%d", 43))); //注:printf函數的返回值是打印在屏幕上字符的個數 return 0; }
- 告訴編譯器有一個函數叫什么,參數是什么,返回類型是什么。但是具體是不是存在,函數 聲明決定不了。
- 函數的聲明一般出現在函數的使用之前。要滿足先聲明后使用。
- 函數的聲明一般要放在頭文件中的。
函數聲明的格式:
dataType functionName( dataType1 param1, dataType2 param2 … );
有了函數聲明,函數定義就可以出現在任何地方了,甚至是其他文件、靜態鏈接庫、動態鏈接庫等。
簡單來說,“函數聲明”的作用是把函數的名字、函數類型以及形參類型、個數和順序通知編譯系統,以便在調用該函數時系統按此進行對照檢查(例如函數名是否正確,實參與形參的類型和個數是否一致)
函數的定義是指函數的具體實現,交待函數的功能實現。
void Swap1(int *px, int *py);//函數的聲明void Swap(int *px, int *py)//函數定義{ int z = 0; z = *px; *px = *py; *py = z;}int main(){ int a = 10; int b = 20; printf("交換前a=%d,b=%d/n", a, b); Swap(&a,&b); printf("交換后a=%d,b=%d/n", a, b); return 0;}
1、函數的聲明與函數的定義形式上十分相似,但是二者有著本質上的不同。聲明是不開辟內存的,僅僅告訴編譯器,要聲明的部分存在,要預留一點空間。定義則需要開辟內存。
函數的定義
函數的定義是一個完整的函數單元:
包含函數類型、函數名、形參及形參類型、函數體等在程序中,函數的定義只能有一次函數首部與花括號間不加分號
函數的聲明
函數聲明只是對編譯系統的一個說明:
函數聲明是對定義的函數的返回值的類型說明,以通知系統在本函數中所調用的函數是什么類型。不包含函數體(或形參)調用幾次該函數就應在各個主調函數中做相應聲明函數聲明是一個說明語句,必須以分號結束!
函數還有很多其他的知識,本文只是略作探討。函數在我們編程之中占據重要地位,只有學好了函數,我們才能在接下的學習之中更好的前進。
!!! 感謝各位看到這里,小弟不才,文中若有錯誤之處,還望指出,共同探討,共同進步!!!
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/119675.html
摘要:如果我們要將的地址保存到中,我們需要我們給指針變量相應的類型。類型的指針是為了存放類型變量的地址這里可以看到,指針的定義方式是類型名指針變量名。如下最后本文介紹的是指針的基礎知識,往后還會繼續深入講解指 ...
摘要:所以,遞歸在編程中同樣是很重要的一個知識點。舉個例子用遞歸實現求第個斐波那契數。總結起來四個字大事化小繼續舉斐波那契數的例子三遞歸是怎樣運行的我們通過一道題目來講解。 ...
摘要:本人計劃編寫一個針對中初級前端開發者學習的系列教程玩轉。使用的原因是新的語言規范開發效率更高代碼更優雅,尤其是基于開發的項目。其次也是目前特別流行的一個前端框架,截止目前,上有將近萬,國內一二線互聯網公司都有深度依賴開發的項目。 本人計劃編寫一個針對中初級前端開發者學習 React 的系列教程 - 《玩轉 React》。 文章更新頻率:每周 1 ~ 2 篇。 目錄 玩轉 React(...
摘要:的翻譯文檔由的維護很多人說,阮老師已經有一本關于的書了入門,覺得看看這本書就足夠了。前端的異步解決方案之和異步編程模式在前端開發過程中,顯得越來越重要。為了讓編程更美好,我們就需要引入來降低異步編程的復雜性。 JavaScript Promise 迷你書(中文版) 超詳細介紹promise的gitbook,看完再不會promise...... 本書的目的是以目前還在制定中的ECMASc...
閱讀 1649·2021-11-16 11:44
閱讀 2392·2021-10-11 11:07
閱讀 4036·2021-10-09 09:41
閱讀 662·2021-09-22 15:52
閱讀 3187·2021-09-09 09:33
閱讀 2700·2019-08-30 15:55
閱讀 2284·2019-08-30 15:55
閱讀 837·2019-08-30 15:55