-
函數(shù)的概述
一個(gè)較大的程序可分為若干個(gè)程序模塊,每一個(gè)模塊用來實(shí)現(xiàn)一個(gè)特定的功能。在高級(jí)語言中用子程序?qū)崿F(xiàn)模塊的功能浊洞。子程序由函數(shù)來完成牵敷。一個(gè)C程序可由一個(gè)主函數(shù)和若干個(gè)其他函數(shù)構(gòu)成。函數(shù)的調(diào)用關(guān)系:由主函數(shù)調(diào)用其他函數(shù),其他函數(shù)也可以互相調(diào)用法希。同一個(gè)函數(shù)可以被一個(gè)或多個(gè)函數(shù)調(diào)用任意多次枷餐。如下圖所示:
//例1
/# include <stdio.h>
void main()
{
void printstar(); /對(duì)printstar函數(shù)聲明/
void print_message(); /對(duì)print_message函數(shù)聲明/
printstar(); /調(diào)用printstar函數(shù)/
print_message(); /調(diào)用print_message函數(shù)/
printstar(); /調(diào)用printstar函數(shù)/
}
void printstar() /定義printstar函數(shù)/
{
printf("* * * * * * * * * * * * * * * *\n");
}void print_message() /定義print_message函數(shù)/
{
printf("How do you do!\n");
}
//輸出:
/* * * * * * * * * * * * * * * *
How do you do!
/* * * * * * * * * * * * * * * *
(注:定義函數(shù)可以在主函數(shù)之前定義也可以在主函數(shù)之后定義,但是需要注意定義的順序不同是有差異的苫亦。1)在主函數(shù)之前定義毛肋,則在主函數(shù)(或其他函數(shù))調(diào)用該函數(shù)時(shí)不需要再聲明,直接調(diào)用即可屋剑;2)在主函數(shù)之后定義润匙,則在主函數(shù)(或其他函數(shù))調(diào)用該函數(shù)時(shí)需要聲明,再調(diào)用唉匾,否則會(huì)出錯(cuò)孕讳。(為了養(yǎng)成良好的書寫習(xí)慣匠楚,在調(diào)用函數(shù)時(shí)都事先進(jìn)行聲明,再調(diào)用))
函數(shù)的相關(guān)說明:1)一個(gè)C程序有一個(gè)或多個(gè)程序模塊組成厂财,每個(gè)程序模塊作為一個(gè)源程序文件芋簿。、對(duì)于較大的程序璃饱,一般是將其分割為若干個(gè)子程序模塊与斤。這樣便于分別編寫、分別編譯荚恶,以提高調(diào)試效率撩穿。(一個(gè)源程序文件可以為多個(gè)C程序公用)
2)一個(gè)源程序文件由一個(gè)或多個(gè)函數(shù)以及其他有關(guān)內(nèi)容(如命令行、數(shù)據(jù)定義等)組成谒撼。一個(gè)源程序文件是一個(gè)編譯單位,在程序編譯時(shí)是以源程序文件為單位進(jìn)行編譯的,而不是以函數(shù)為
單位進(jìn)行編譯的食寡。
3)C程序的執(zhí)行是從main函數(shù)開始的,如是在main函數(shù)中調(diào)用其他函數(shù),在調(diào)用后流程返回到main函數(shù),在main函數(shù)中結(jié)束整個(gè)程序的運(yùn)行。
4) 所有函數(shù)都是平行的,即在定義函數(shù)時(shí)是分別進(jìn)行的,是互相獨(dú)立的嗤栓。一個(gè)函數(shù)并不從屬于另一函數(shù),即函數(shù)不能嵌套定義(但是可以嵌套調(diào)用)冻河。函數(shù)間可以互相調(diào)用,但不能調(diào)用main函數(shù)。main函數(shù)是系統(tǒng)調(diào)用的茉帅。
5)從用戶使用的角度看,函數(shù)有兩種:
(1)標(biāo)準(zhǔn)函數(shù),即庫函數(shù)叨叙。這是由系統(tǒng)提供的,用戶不必自己定義這些函數(shù),可以直接使用它們。應(yīng)該說明,不同的C系統(tǒng)提供的庫函數(shù)的數(shù)量和功能會(huì)有一些不同,當(dāng)然許多基本的函數(shù)是共同的堪澎。
(2)用戶自己定義的函數(shù)擂错。用以解決用戶的專門需要。
6)從函數(shù)的形式看,函數(shù)分兩類:
(1)無參函數(shù)樱蛤。如例1中的printstar()和print_message()就是無參函數(shù)钮呀。在調(diào)用無參函數(shù)時(shí),主調(diào)函數(shù)不向被調(diào)用函數(shù)傳遞數(shù)據(jù)。無參函數(shù)一般用來執(zhí)行指定的一組操作昨凡。例如,例1程序中的printstar函數(shù)爽醋。
(2)有參函數(shù)。在調(diào)用函數(shù)時(shí),主調(diào)函數(shù)在調(diào)用被調(diào)用函數(shù)時(shí),通過參數(shù)向被調(diào)用函數(shù)傳遞數(shù)據(jù),一般情況下,執(zhí)行被調(diào)用函數(shù)時(shí)會(huì)得到一個(gè)函數(shù)值,供主調(diào)函數(shù)使用便脊。 如例2
//例2
/#include<stdio.h>
int max(int x, int y) /* 這里就是在函數(shù)被調(diào)用時(shí)傳入?yún)?shù)x蚂四,y /
{
int z;
z = x > y ? x : y;
return z; //該函數(shù)執(zhí)行結(jié)束后返回z的值 */
}void main()
{
int max(int x, int y);
int i, j, k;
printf("Please input two numbers: ");
scanf("%d%d", &i, &j);
k = max(i, j);
printf("The maximum number is: %d\n", k);
}
//Please input two numbers: 15 16
The maximum number is: 16
函數(shù)定義的一般形式
定義無參函數(shù)的一般形式:
類型標(biāo)識(shí)符 函數(shù)名() /* 這里的類型標(biāo)識(shí)符即為返回值的類型 /
{
聲明部分
語句部分
}
定義有參函數(shù)的一般形式:
類型標(biāo)識(shí)符 函數(shù)名(形式參數(shù)列表) / 這里的類型標(biāo)識(shí)符即為返回值的類型 */
{
聲明部分
語句部分
}
定義控函數(shù)的一般形式:(注:空函數(shù)被調(diào)用時(shí)什么也不做,其目的是為以后擴(kuò)展程序功能做準(zhǔn)備)
類型標(biāo)識(shí)符 函數(shù)名()
{
哪痰;
}-
函數(shù)的參數(shù)和函數(shù)的值
形參(形式參數(shù)):在定義有參函數(shù)時(shí)遂赠,函數(shù)名后面括號(hào)中的變量名稱即為“形式參數(shù)”。(注:形參不占內(nèi)存晌杰,只有當(dāng)調(diào)用該函數(shù)時(shí)跷睦,傳入實(shí)參才開辟內(nèi)存空間)(注2:在定義形參時(shí)需要聲明其數(shù)據(jù)類型,如果沒有聲明則系統(tǒng)默認(rèn)為int型肋演。)
實(shí)參(實(shí)際參數(shù)):在主函數(shù)調(diào)用一個(gè)函數(shù)時(shí)抑诸,函數(shù)名后面括弧中的參數(shù)(也可以是一個(gè)表達(dá)式)稱為“實(shí)際參數(shù)”烂琴。(注:實(shí)參是占內(nèi)存的)
在多數(shù)情況下,主調(diào)函數(shù)和被調(diào)函數(shù)之間室友數(shù)據(jù)傳遞關(guān)系的哼鬓。(在不同的函數(shù)之間傳遞數(shù)據(jù)可以使用:1)參數(shù):通過形參和實(shí)參监右;2)返回值:函數(shù)通過return返回計(jì)算結(jié)果給調(diào)用它的函數(shù)边灭;3)全局變量)形參與實(shí)參的說明:
1)在定義函數(shù)中指定的形參,在未出現(xiàn)函數(shù)調(diào)用時(shí),它們并不占內(nèi)存中的存儲(chǔ)單元异希。只有在發(fā)生函數(shù)調(diào)用時(shí),函數(shù)max(int x, int y)中的形參才被分配內(nèi)存單元。在調(diào)用結(jié)束后,形參所占的內(nèi)存單元也被釋放绒瘦。
2)實(shí)參可以是常量称簿、變量或表達(dá)式,如:max(3,a+b); 但要求它們有確定的值。在調(diào)用時(shí)將實(shí)參的值賦給形參惰帽。
3)在被定義的函數(shù)中,必須指定形參的類型憨降。(注:如果沒有制定類型,編譯器會(huì)warning该酗,但是默認(rèn)該形參為int型授药。為了養(yǎng)成良好的書寫習(xí)慣應(yīng)該指定形參類型。)
4)實(shí)參與形參的類型應(yīng)相同或賦值兼容呜魄。(如果形參與實(shí)參類型不同悔叽,則系統(tǒng)自動(dòng)將實(shí)參轉(zhuǎn)換為形參的數(shù)據(jù)類型。)見例3
//例3
/#include<stdio.h>
int max(int x, int y)
{
int z;
z = x > y ? x : y;
printf("The max number is: %d \n", z);
return z;
}
void main()
{
float i = 15.5, j = 16.5;
printf("The maximum number is: %d\n", max(i, j));
}
//輸出: The max number is: 16
The maximum number is: 16
5)在C語言中,實(shí)參向?qū)π螀⒌臄?shù)據(jù)傳遞是“值傳遞”(相當(dāng)于COPY),單向傳遞,只由實(shí)參傳給形參,而不能由形參傳回來給實(shí)參爵嗅。在內(nèi)存中,實(shí)參單元與形參單元是不同的單元娇澎。在調(diào)用函數(shù)時(shí),給形參分配存儲(chǔ)單元,并將實(shí)參對(duì)應(yīng)的值傳遞給形參,調(diào)用結(jié)束后,形參單元被釋放,實(shí)參單元仍保留并維持原值。因此,在執(zhí)行一個(gè)被調(diào)用函數(shù)時(shí),形參的值如果發(fā)生改變,并不會(huì)改變主調(diào)函數(shù)的實(shí)參的值睹晒。例如,若在執(zhí)行函數(shù)過程中x和y的值變?yōu)?0和15,而a和b仍為2和3趟庄。
函數(shù)的返回值:通常,希望通過函數(shù)調(diào)用使主調(diào)函數(shù)能得到一個(gè)確定的值,這就是函數(shù)的返回值伪很。戚啥、
1)函數(shù)的返回值是通過函數(shù)中的return語句獲得的:return語句將被調(diào)用函數(shù)中的一個(gè)確定值帶回主調(diào)函數(shù)中去。(需要返回值則return锉试,不需要?jiǎng)t不用)(一個(gè)函數(shù)中可以有一個(gè)以上的return語句,執(zhí)行到哪一個(gè)return語句,哪一個(gè)語句起作用猫十。)
2)函數(shù)的返回值應(yīng)當(dāng)屬于某一個(gè)確定的類型,在定義函數(shù)時(shí)指定函數(shù)返回值的類型。
3)在定義函數(shù)時(shí)指定的函數(shù)類型一般應(yīng)該和return語句中的表達(dá)式類型一致键痛。(如果函數(shù)值的類型和return語句中表達(dá)式的值不一致,則以函數(shù)類型為準(zhǔn)炫彩。對(duì)數(shù)值型數(shù)據(jù),可以自動(dòng)進(jìn)行類型轉(zhuǎn)換。即函數(shù)類型決定返回值的類型絮短。)
4)對(duì)于不帶回值的函數(shù),應(yīng)當(dāng)用“void”定義函數(shù)為“無類型”(或稱“空類型”)江兢。(這樣,系統(tǒng)就保證不使函數(shù)帶回任何值,即禁止在調(diào)用函數(shù)中使用被調(diào)用函數(shù)的返回值。此時(shí)在函數(shù)體中不得出現(xiàn)return語句丁频。)
- 函數(shù)的調(diào)用
-
函數(shù)調(diào)用一般形式:函數(shù)名(實(shí)參列表)(注:調(diào)用無參函數(shù)杉允,則括號(hào)為空邑贴;如果實(shí)參列表包含多個(gè)實(shí)參,則各參數(shù)間用逗號(hào)隔開叔磷。實(shí)參與形參的個(gè)數(shù)應(yīng)該相等拢驾,類型應(yīng)匹配。(對(duì)實(shí)參列表中實(shí)參的求值順序并不是確定的改基,有的編譯器按照自左向右的順序繁疤,有的按照自右向左的順序。
-
* 函數(shù)調(diào)用的三種方式:1)函數(shù)語句:把函數(shù)作為一個(gè)語句稠腊。有時(shí)不需要函數(shù)有任何返回值,只要求函數(shù)完成一定的操作鸣哀。
2)函數(shù)表達(dá)式:函數(shù)出現(xiàn)在一個(gè)表達(dá)式中架忌,這種表達(dá)式稱為函數(shù)表達(dá)式。這時(shí)要求函數(shù)帶回一個(gè)確定的值我衬,用以參加表達(dá)式的運(yùn)算叹放。例:c = 2 * max(a, b);
3)函數(shù)參數(shù):函數(shù)調(diào)用作為一個(gè)函數(shù)的實(shí)參。例如: m = max(a, max(b, c)); 又例:printf(“%d”, max(a, b));
* 對(duì)被調(diào)用函數(shù)的聲明和函數(shù)原型:
1)被調(diào)用函數(shù)必須是一個(gè)已經(jīng)存在的函數(shù)挠羔。
2)如果調(diào)用庫函數(shù)(或其他源程序文件中的函數(shù))井仰,應(yīng)該在源程序文件開頭用#include命令將調(diào)用的有關(guān)庫函數(shù)(或其他源程序文件中的函數(shù))所需要的信息“包含”到本文件中。
3)如果使用用戶自己定義的函數(shù)褥赊,而該函數(shù)的位置與調(diào)用它的函數(shù)在同一個(gè)源程序文件中糕档,則只需要在調(diào)用該函數(shù)的的函數(shù)中做出聲明,在調(diào)用即可拌喉。如例4速那,
//例4
/#include<stdio.h>
int max(int x, int y)
{
int z;
z = x > y ? x : y;
printf("The max number is: %d \n", z);
return z;
}
void main()
{
int i = 15, j = 16;
printf("The maximum number is: %d\n", max(i, j));
}
//輸出: The max number is: 16
The maximum number is: 16
- 函數(shù)的定義與聲明:
函數(shù)的聲明的作用:是把函數(shù)的名字、函數(shù)類型以及形參的類型尿背、個(gè)數(shù)和順序通知編譯系統(tǒng),以便在調(diào)用該函數(shù)時(shí)系統(tǒng)按此進(jìn)行對(duì)照檢查端仰。(例如函數(shù)名是否正確,實(shí)參與形參的類型和個(gè)數(shù)是否一致)(不占內(nèi)存)
函數(shù)的定義:是指對(duì)函數(shù)功能的確立,包括指定函數(shù)名,函數(shù)值類型、形參及其類型田藐、函數(shù)體等,它是一個(gè)完整的荔烧、獨(dú)立的函數(shù)單位。(占內(nèi)存)
- 函數(shù)的嵌套調(diào)用
- C語言中函數(shù)不可以嵌套定義汽久,但是可以嵌套調(diào)用鹤竭。(即一個(gè)被調(diào)用的函數(shù)中調(diào)用另外一個(gè)函數(shù)或多個(gè)函數(shù)。(類似于俄羅斯套娃))景醇。見例5臀稚,
//例5
/#include<stdio.h>
int max(int x, int y)
{
int z;
int min(int a, int b);
min(x, y);
z = x > y ? x : y;
printf("The max number is: %d \n", z);
return z;
}
int min(int a, int b)
{
int z;
z = a < b ? a : b;
printf("The min number is: %d\n", z);
}
void main()
{
int i = 15, j = 16;
printf("The maximum number is: %d\n", max(i, j));
}
//輸出: The min number is: 15
The max number is: 16
The maximum number is: 16
(這里的函數(shù)執(zhí)行順序是:1)main函數(shù);2)max函數(shù)三痰;3)min函數(shù)吧寺;4)打印出min函數(shù)的值窜管;5)返回max函數(shù)的值;6)打印出max函數(shù)的返回值稚机;7)程序結(jié)束)
- 遞歸函數(shù)
遞歸函數(shù)的定義:函數(shù)自身調(diào)用自身即為函數(shù)的遞歸(注意:遞歸函數(shù)必須要有一個(gè)退出條件幕帆,否則將會(huì)無限的執(zhí)行下去。)見例6赖条,例7.
//例6
/#include<stdio.h>
void main()
{
void hanoi(int n, char a, char b, char c);
int n;
char a = '1', b = '2', c = '3';
printf("How many levels of Hanoi do you want?\n");
scanf("%d", &n);
hanoi(n, a, b, c);
}
void hanoi(int n, char a, char b, char c)
{
void move(char i, char j);
if (n == 1) move(a, c);
else{
hanoi(n -1, a, c, b);
move(a, c);
hanoi(n -1, b, a, c);
}
}
void move(char i, char j)
{
printf("%c -> %c\n", i, j);
}
//輸出:How many levels of Hanoi do you want?
//輸入:3
//輸出: 1 -> 3
1 -> 2
3 -> 2
1 -> 3
2 -> 1
2 -> 3
1 -> 3
//分析:(1) 將A上n-1個(gè)盤借助C座先移到B座上失乾。
(2) 把A座上剩下的一個(gè)盤移到C座上。
(3) 將n-1個(gè)盤從B座借助于A座移到C座上谋币。
//例7
/#include<stdio.h>
void main()
{
int i, j = 1, k;
int factorial(int x, int y);
printf("Please input a number: \n");
scanf("%d", &i);
k = factorial(i, j);
printf("The final number is: %d\n", k);
}
int factorial(int x, int y)
{
if (x < 1)
return y;
y = y * x;
x--;
factorial(x, y);
}
//輸出:Please input a number:
輸入:5
輸出:The final number is: 120
- 數(shù)組作為函數(shù)參數(shù)
數(shù)組可以作為函數(shù)的參數(shù)使用,進(jìn)行數(shù)據(jù)傳送仗扬。數(shù)組用作函數(shù)參數(shù)有兩種形式:
1)把數(shù)組元素作為實(shí)參使用; (數(shù)組元素與普通變量并無區(qū)別。因此它作為函數(shù)實(shí)參使用與普通變量是完全相同的,在發(fā)生函數(shù)調(diào)用時(shí),把作為實(shí)參的數(shù)組元素的值傳送給形參,實(shí)現(xiàn)單向的值傳送蕾额。)
2)把數(shù)組名作為函數(shù)的形參和實(shí)參使用。
用數(shù)組名作函數(shù)參數(shù)與用數(shù)組元素作實(shí)參有幾點(diǎn)不同:(1)用數(shù)組元素作實(shí)參時(shí),只要數(shù)組類型和函數(shù)的形參變量的類型一致,那么作為下標(biāo)變量的數(shù)組元素的類型也和函數(shù)形參變量的類型是一致的彼城。因此,并不要求函數(shù)的形參也是下標(biāo)變量诅蝶。換句話說,對(duì)數(shù)組元素的處理是按普通變量對(duì)待的。然而,用數(shù)組名作函數(shù)參數(shù)時(shí),則要求形參和相對(duì)應(yīng)的實(shí)參都必須是類型相同的數(shù)組,都必須有明確的數(shù)組說明募壕。當(dāng)形參和實(shí)參二者不一致時(shí),即會(huì)發(fā)生錯(cuò)誤调炬。
(2)在普通變量或下標(biāo)變量作函數(shù)參數(shù)時(shí),形參變量和實(shí)參變量是由編譯系統(tǒng)分配的兩個(gè)不同的內(nèi)存單元。在函數(shù)調(diào)用時(shí)發(fā)生的值傳送是把實(shí)參變量的值賦予形參變量舱馅。
然而缰泡,在用數(shù)組名作函數(shù)參數(shù)時(shí),不是進(jìn)行值的傳送,即不是把實(shí)參數(shù)組的每一個(gè)元素的值都賦予形參數(shù)組的各個(gè)元素。而是把數(shù)組的首地址賦給形參數(shù)組名代嗤,因此實(shí)參與形參共用同一內(nèi)存空間棘钞。(數(shù)組名就是數(shù)組的首地址。因此在數(shù)組名作函數(shù)參數(shù)時(shí)所進(jìn)行的傳送只是地址的傳送,也就是說把實(shí)參數(shù)組的首地址賦予形參數(shù)組名干毅。形參數(shù)組名取得該首地址之后,也就等于有了實(shí)在的數(shù)組。實(shí)際上是形參數(shù)組和實(shí)參數(shù)組為同一數(shù)組,共同擁有一段內(nèi)存間。)見例8瑰步。
//例8
/#include<stdio.h>
void main()
{
void list2(int a[10]);
int a[10] = {1, 2, 3, 4, -1, -2, -3, -4, 2, 3};
list2(a);
}void list2(int a[10])
{
int i;
for(i = 0; i <= 9; i++)
{
if (a[i] < 0) continue;
else printf("The positive number in array is: %d \n", a[i]);
}
}
//輸出:The positive number in array is: 1
The positive number in array is: 2
The positive number in array is: 3
The positive number in array is: 4
The positive number in array is: 2
The positive number in array is: 3