函式概述
在C語言當中,一個程式,無論複雜或簡單,總體上都是一個“函式”;這個函式就稱為“main() 函式”,也就是“主函式”。比如有個“做菜”程式,那么“ 做菜 ”這個過程就是“主函式”。在主函式中,根據情況,你可能還需要調用“買菜,切菜,炒菜”等子函式。
main函式在程式中大多數是必須存在的,但是依然有例外情況,比如windows編程中可以編寫一個動態程式庫(dll)模組,這是其他windows程式可以使用的代碼。由於DLL模組不是獨立的程式,因此不需要main函式。再比如,用於專業環境的程式-----如機器人中的控制晶片--可能不需要main函式。
參數
C程式最大的特點就是所有的程式都是用函式來裝配的。main()稱之為主函式,是所有程式運行的入口。其餘函式分為有參或無參兩種,均由main()函式或其它一般函式調用,若調用的是有參函式,則參數在調用時傳遞。
在前面課程的學習中,對main()函式始終作為主調函式處理,也就是說,允許main()調用其它函式並傳遞參數。事實上,main()函式既可以是無參函式,也可以是有參的函式。對於有參的形式來說,就需要向其傳遞參數。
我們先看一下main()函式的帶參的形式:
從函式參數的形式上看,包含一個整型和一個指向字元指針的指針。當一個C的源程式經過編譯、連結後,會生成擴展名為.EXE的執行檔(對windows作業系統而言),這是可以在作業系統下直接運行的檔案,換句話說,就是由系統來啟動運行的。由系統在啟動運行時傳遞參數。
在作業系統環境下,一條完整的運行命令應包括兩部分:命令與相應的參數。其格式為:
命令參數1參數2....參數nt;
此格式也稱為命令行。命令行中的命令就是執行檔的檔案名稱,其後所跟參數需用空格分隔,並為對命令的進一步補充,也即是傳遞給main()函式的參數。
命令行與main()函式的參數存在如下的關係:
設命令行為:program str1 str2 str3 str4 str5
其中program為檔案名稱,也就是一個由program.c經編譯、連結後生成的執行檔program.exe,其後各跟5個參數。對main()函式來說,它的參數argc記錄了命令行中命令與參數的個數,共6個,指針數組的大小由參數argc的值決定,即為char*argv[6],指針數組的取值情況如圖6-15所示。
數組的各指針分別指向一個字元串。應當引起注意的是接收到的指針數組的各指針是從命令行的開始接收的,首先接收到的是命令,其後才是參數。
下面用實例來說明帶參數的main()函式的正確使用。
[例6-29] 利用圖形庫函式繪製一個變化的環。它是把一個半徑為R 1的圓周分成n份,然後以每個等分點為圓心,以R s為半徑畫n個圓(關於作圖的詳細理論本教材第9章第1節作了專門介紹,這裡只作簡單分析)。利用main()函式的帶參數形式,我們可以從鍵盤以命令行的方式輸入R 1和R s及螢幕的背景色。
若程式名為L6-29.c,經編譯、連結生成執行檔L6-29.exe。在作業系統的環境下運行程式,命令行方式為:
具體步驟:
1、Win + R打開運行;
2、輸入cmd打開命令行;
3、進入到要執行的exe檔案所在目錄,如要要執行E:\程式設計\Ctest.exe檔案,則輸入E:回車(注意:如果要更改其他盤目錄必須首先進入要進入盤的根目錄,例如進入E盤則輸入E:不用輸入cd E:)進入E盤根目錄,再輸入cd E:\程式設計 則進入了當前目錄,最後就可以輸入參數了,例如Ctest yishi weban回車即可(Ctest為要執行的執行檔,後面兩個也為要傳遞給main函式的參數);
l6-29 40 20 3
則命令行與main()函式的參數有如圖6-16所示的關係
圖6-16中,argv[0]是程式名,argv[1]是r1的值,
argv[2]是rs的值,argv[3]是螢幕的背景色。
由於指針數組均存放字元串,所需的圓半徑及背景
色彩通過atoi()函式轉換為整型。
通過帶參數的main()函式,我們可以為自己的程式設定口令,在運行程式的命令行中給出所需的口令,正確則繼續,否則退出。程式圖形輸出如圖6-17所示。
[例6-30]將上述程式作修改,在程式的入口處添置密碼,若給定密碼正確,則顯示圖
形。
在作業系統的環境下運行程式, 命令行中增加口令“pass”,命令行方式為:
l6-30 pass 20 40 3
指針數組的存儲字元串如圖6-18所示。
若給定字元串argv[1]的值是pass,則程式正確運行,否則程式退出。口令正確的情況下,顯示的圖形為圖6-17中的一個。
函式分類
從用戶使用的角度看,函式有兩種:
1、標準函式,即庫函式。這是由系統提供的。
2、用戶自定義的函式。可以解決用戶的專門需要。
二、從函式的形式看,函式分兩類:
1、無參函式。printstar和print_message就是無參函式。在調用無參函式時,主調函式並不將數據傳送給被調用函式,一般用來執行指定的一組操作。
2、有參函式。在調用函式時,在主調函式和被調用函式之間有數據傳遞。也就是說,主調函式可以將數據傳遞給被調用函式使用,被調用函式中的數據也可以帶回來供主調函式使用。
一般形式
無參函式
類型標示符 函式名()
{
函式體
}
有參函式定義
類型標示符 函式名 (形式參數列表)
{
函式體
}
可以有空函式
它的形式為
類型說明符 函式名()
{ }
例如:
dummy(){}
傳統方式
在老版本c語言中,對形參類型的聲明是放在函式定義的第二行,也就是不在第一行的括弧內指定形參的類型,而在括弧外單獨指定,例如上面定義的max函式可以寫成一下形式:
返回值
在 C89 標準中,main( ) 是可以接受的。Brian W. Kernighan 和 Dennis M. Ritchie 的經典巨著 The C programming Language 用的就是 main( )。不過在最新的 C99 標準中,只有以下兩種定義方式是正確的:
其中char **argv可以寫成char *argv[],兩者等價
main 函式的返回值類型必須是 int ,這樣返回值才能傳遞給程式的激活者(如作業系統)。
如果 main 函式的最後沒有寫 return 語句的話,C99 規定編譯器要自動在生成的目標檔案中(如 exe 檔案)加入return 0; ,表示程式正常退出。不過,我還是建議你最好在main函式的最後加上return 語句,雖然沒有這個必要,但這是一個好的習慣。
也就是說在最新的C語言標準中強制要求main函式的返回值類型為int,main函式的返回值是傳遞給作業系統,讓作業系統判斷程式的執行情況(是正常結束還是出現異常)
誤區
很多人甚至市面上的一些書籍,都使用了void main() ,其實這是錯誤的。C/C++中從來沒有定義過void main()。C++之父Bjarne Stroustrup在他的主頁上的FAQ中明確地寫著The definition void main() {/*...*/} is not and never has been C++, nor has it even been C.(void main() 從來就不存在於C++或者C)。
在C和C++中,不接收任何參數也不返回任何信息的函式原型為“void foo(void);”。可能正是因為這個,所以很多人都誤認為如果不需要程式返回值時可以把main函式定義成void main(void) 或void main()。然而這是錯誤的!main函式的返回值應該定義為int類型,C和C++標準中都是這樣規定的。雖然在一些編譯器中,void main可以通過編譯(如vc6),但並非所有編譯器都支持void main,因為標準中從來沒有定義過void main。g++3.2、dev C++等環境中如果main函式的返回值不是int類型,根本無法通過編譯。而gcc3.2則會發出警告。所以,如果你想你的程式擁有很好的可移植性,請一定要用int main。
套用
C++中的main函式
C++繼承了C語言的大部分特性,因此保留了“程式總是從main函式開始執行,且總是默認從main函式的return語句或結尾處結束運行”這一傳統,但是要注意,C++中的main函式要想作為程式執行的出入口,必須寫在全局(Global)範圍,不能寫成某個結構體或某個類的成員。雖然main函式可以作為結構體或者類的成員函式,但相應地會失去作為程式出入口的功能。
C++中全局main函式的書寫格式與C語言完全相同,功能也完全相同,且同一C++程式同樣只能有一個全局main函式。
Java中的main函式
Java同樣是以main函式作為程式執行出入口的,但Java作為“更純潔”的面向對象語言,它的main函式與C/C++有很大的不同。
首先,返回值的概念淡化,在Java Application中main不允許返回值,因此int main是被禁止的,必須使用void main,int main僅限在JavaBean中使用。
其次,Java中所有的函式必須屬於類,沒有什麼全局函式一說,因此main函式不能是全局成員,必須是某個類的成員。
第三,由於main函式變成了類的成員函式,因此要想直接被系統調用,還必須使用public static使其成為靜態函式並具有公開許可權。
第四,main函式的參數被簡化,只需要提供字元串數組即可,不需要提供參數個數(這是由於Java的數組具有下標檢查功能的原因)
Java Application中的main函式一般格式如下(類名可以自定義,但保存為Java源碼時,主檔案名稱必須與類名相同,否則可能無法運行)
Java Applet的運行機制與Java Application完全不同,因此不需要main函式
C#中的main函式
C#中的main函式與Java大同小異,同樣必須是類成員,同樣使用字元串數組作唯一參數,同樣是靜態函式,同樣的void main,與之不同的是:main的首字母變成了大寫,即"Main函式“,且是否限定為public級別已經無所謂了(默認沒有public,但某些場合可能還是需要public)
另外,需要注意的是,C#中不再有”類名必須與主檔案名稱同名“的限制,即使類名不和主檔案名稱相同,程式照樣可以運行。
C#應用程式中的main函式默認是這樣的(注意main的首字母已是大寫)
C#和C/C++、java不同的是C#不在拘泥於必須從main()函式開始執行,C#是屬於事件觸發。