8、C語言之函數
一、函數淺析
1、函數
函數是一個可以反復使用的程序段,從其它的程序段中均可以通過調用語句來使用這個程序段,完成既定的工作
說明:
(1)建立函數稱為“函數定義”,使用函數稱為“函數調用”
(2)調用其它函數的函數稱為“主調函數”,而被調用的函數稱為“被調函數”
一個實用的C語言源程序總是由許多函數組成,這些函數都是根據實際任務,由用戶自己來編寫,在這些函數中可以調用C提供的庫函數,也可以調用由用戶自己或他人編寫的函數。
但是,一個C語言源程序無論包含了多少函數,在正常情況下總是從main函數開始執行,main函數結束
C語言源程序可以分放在不同的文件中,所以一個源程序中的函數也可以分放在不同的文件中。
2、庫函數
C語言提供了豐富的庫函數,包括常用的數學函數、字符和字符串處理函數,輸入輸出函數等等。
調用C語言標準庫函數時要求的include命令行
#include<stdio.h>
3、函數的定義
定義格式:
函數類型 函數名(形參類型說明表)
{
說明部分
語句部分
}
(1)函數有“函數頭”和“函數體”兩部分組成;函數體由語句和其他分程序組成
(2)函數類型規定了函數返回值的數據類型,若無返回值,則數據類型為void,如果函數有返回值,則在函數體中應有一條返回語句“return 表達式;”,無返回值,則返回語句應為“return;”也可以省略。
(3)形式參數表時逗號分隔的若幹形式參數,每個形式參數可以時一個變量名、數組名、指針變量名和指針數組名,形參列表中每個參數的數據類型必須給出。
(4)形式參數可以為空,但是圓括號不能省略
(5)形參若是數組,只需給出數組名,[]中數組長度不許給出
(6)函數體中不允許再嵌套定義函數,能嵌套調用
函數返回值
函數的值通過return語句返回,return語句的形式如下:
return 表達式; 或 return (表達式);
說明:
(1)return語句中的表達式的值就是所求的函數值,此表達式的值的類型必須與函數首部所說明的類型一致。若類型不一致,則以函數值的類型為主,由系統自動轉換。(可以寫個函數測試以下)
(2)無論函數體中有多少個return語句,return語句只可能執行一次;
(3)return語句中可以不含表達式,這時必須定義函數為void類型。
(4)函數體內可以沒有return語句,只是也必須定義函數為void類型。
函數調用
形式:函數名(實際參數表)
(1)沒有返回值的函數調用格式:
函數名(實際參數表);
(2)有返回值的函數調用格式:
x=函數名(實際參數表);
二、函數的深析
1、基本思想:
將一個大程序按功能分割成一些小模塊
特點:
各個模塊相對獨立、功能單一、結構清晰、接口簡單
控制了程序的復雜性
提高原件的可靠性
縮短開發周期
避免程序開發的重復勞動
易於維護和功能擴充
開發方法
自上向下,逐步分解,分而治之
函數調用過程分析
(1)為函數的所有形參分配內存單元
(2)計算各個實參表達式的值,一一對應的賦值個相應的形參(若無形參,上述過程不執行)
(3)進入函數體,執行函數中的語句,實現函數的功能
(4)執行到return語句時,計算return語句中的表達式的值,(若無返回值函數,本項不做),返回到主調函數
(5)釋放形參及本函數內的局部變量所占的內存,繼續執行主調函數中的後繼語句
2、函數間的傳值
C語言中,主調函數和被調函數之間的數據可以通過三種方式進行傳遞
(1)值傳遞
值傳遞是個單向傳遞過程,兩個單向傳遞構成雙向傳遞
主調函數的內容傳遞給被調函數:
實際參數賦值給形式參數
(在C語言中,數據只能從實際參數單向傳遞給形參,俗稱“按值”傳遞,用戶不能再函數中改變對應實參的值)
被調函數的內容傳給主調函數
通過return語句把內容賦給主調函數
1 #include<stdio.h> 2 int fun(int x,int y) 3 { 4 if(x==y) 5 return x; 6 else 7 return ((x+y)/2); 8 } 9 void main() 10 { 11 int a = 4,b=5,c=6; 12 printf("%d\n",fun(2*a,fun(b,c)));//值傳遞 13 return 0; 14 }
(2)地址傳遞
方式:函數調用時,將數據的存儲地址作為參數傳遞給形參,當然此時的形參只能時存儲地址的變量(指針變量)。才能達到“雙向”傳送的目的。
數組名可作為函數參數。(實參和形參都應用數組名)
(3)全局變量傳遞(這不是一種好的方式,通常不推薦使用)
3、函數的嵌套調用和遞歸調用
(1)函數的嵌套調用
函數甲調用了函數乙,而函數乙又調用了函數丙。C規定:函數定義不可嵌套,但可以嵌套調用函數。
(2)函數的遞歸調用
函數直接或間接的調用自身叫做函數的遞歸調用
遞歸的特點:
遞歸必須有遞歸結束條件;
遞歸過程首先是一級一級遞推(即當前調用未結束又引出下一層調用),而滿足遞歸結束條件時結束遞推,再一級一級的回歸(即一級一級再返回上一級的調用繼續完成上一級的未完成的操作)。
說明:
C編譯系統對遞歸函數的自調用次數沒有限制,每調用函數一次,在內存堆棧區分配空間,用於存放函數變量、返回值等信息,所以遞歸次數過多,可能引起堆棧溢出。
1 #include<stdio.h> 2 int fac(int n) 3 { 4 int t; 5 if(n == 1 || n ==0)//遞歸結束條件 6 return 1; 7 else 8 { 9 t = n*fac(n-1);//有規律地遞減 10 return t;//返回上一層調用 11 } 12 } 13 void main() 14 { 15 int m, y; 16 printf("Enter m:"); 17 scanf("%d",&m); 18 if(m < 0) 19 printf("Input data error!\n"); 20 else 21 { 22 y = fac(m); 23 printf("\n%d! = %d\n",m,y); 24 } 25 return 0; 26 }
補充知識:
變量時對程序中數據的存儲空間的抽象
(1)局部變量
定義:在函數內定義,只在函數內有效
使用:不同函數中同名變量占不同的存儲單元
說明:形參屬於局部變量
(2)全局變量
定義:在函數外面定義的變量
外部變量的作用域:對伊只有一個源程序文件構成的程序,外部變量的作用域時從定義它的位置開始,直至它所在源程序文件的結束
特點:外部變量的使用增加了函數之間傳遞數據的途徑,在外部變量的作用域內的任何函數都能引用該外部變量,一個函數對外部變量的修改,能影響到其他引用這個變量的函數;因此對外部變量的使用不當,會產生意外的錯誤。
8、C語言之函數