計算機編程中,入口點是在程序中執行第一條指令的地方,和程序訪問命令行參數的地方。要開始一個程序的執行裝載器操作系統會將控制權傳遞到它的入口點。(在引導期間,操作系統自身就是這個程序)。這標誌着從裝載時(和動態連接時,如果存在的話)到運行時的轉變。

C#中主函數的例子。
C#源代碼中Main()的樣子。標記了不同部分用於參考。

對於某些操作系統和編程語言,入口點是運行時庫,它是一組對語言的支持函數。庫代碼初始化程序並且接着把控制權傳遞給程序本身。在其他情況下,程序自身可以初始化運行時庫。在簡單的系統中,執行開始於第一條語句,這常見於解釋型語言,簡單的可執行格式,和引導裝載器中。在其他情況下,入口點是在某個其他已知內存地址,這可以是絕對地址或相對地址(偏移量)。

可作為替代選擇,程序的執行可以開始於命名點,要麼是編程語言或操作系統定義的約定名字,要麼是調用者指定的名字。在很多C家族語言中,這是叫做main的函數;作為結果,入口點經常叫做主函數。在JVM語言比如Java中,入口點是叫做main的靜態方法;在CLI語言比如C#中,入口點是叫做Main的靜態方法[1]

用法

編輯

在現代的計算機體系中,CPU 下一次要執行的指令地址由一個寄存器指出,稱為「指令指針」(Instruction Pointer、IP)或「程序計數器」(Program Counter、PC)。該寄存器在系統上電或復位時由硬件電路置為某地址值,位於該地址的程序即可視為整個程序的入口點。這個概念一般只在嵌入式程序(固件)或操作系統的引導代碼中使用,因為給非嵌入式系統寫的程序通常包含數量龐大的機器指令、以至於關注一兩個機器指令是沒有意義的。

而所謂的「可執行」,說白了就是這個文件存儲了一些信息、好創造某個讓程序可以開始運行的內存狀態,而操作系統裝載並創建進程的步驟就是把這個滿是機器指令的內存狀態復原出來並開始運行。因此,可執行文件中的「程序入口點」表示把加載進來的哪個地址當作「開始運行」的那一條指令。

編程語言

編輯

C語言C++程式語言,main的函式原型如下所示:

int main(void)
int main()
int main(int argc, char *argv[])

main的兩個環境參數:argcargument count)與argvargument vector[2],兩者個別自程式的指令列給予參數的數量與參數陣列的指標位址。argcargv這兩個參數的名稱,在程式語言的命名規則底下,雖然可以依照使用者的喜好自行定義,但是一般在使用上,還是會以現有的名稱argcargv來進行程式的編寫。其他具有相依平台的格式也可以被C與C++標準所接受;例如,UNIX(非POSIX.1)與Microsoft Visual C++有第三個參數,是用來接收程式的環境變數,利用其他方法存取環境變數,可以使用stdlib.h標頭檔案定義的getenv函式:

int main(int argc, char *argv[], char *envp[])

Mac OS XApple Darwin有第四個參數,它含有作業系統支援性的資訊,例如執行二進制檔案的路徑:[3]

int main(int argc, char *argv[], char *envp[], char *apple[])

main傳給作業系統的傳回值,代表程序處理的結束狀態,在C的標準裡有定義兩個傳回值:EXIT_SUCCESS(通常是整數零 0值)與EXIT_FAILURE。由於在實作上考量到各種的可能性,所以依照可能會發生的狀態來定義傳回值。

依照一般使用的規則,指令列參數的第一個元素就是程式檔案的名稱,假如程式檔案的名稱為rm.exe,當使用者在指令列輸入rm file後,使用者介面的程式shell會初始化rm.exe處理程序,設定環境變數argc = 2以及argv = ["rm", "file"]

main這個名稱是一個特有的名稱;正常來說,使用者在每個C與C++程式自定的函式名稱,必須不同於main這個名稱。

在C++裡,main一定是在全域的名稱空間內(例如:::main),它不可以是類別或是實體的成員函式。

由於前置處理器的關係,以下main函式原始碼可適用於Microsoft Visual C++Dev-C++

#ifndef _MSC_VER
int
#else
void
#endif
main(int argc, char** argv)
{
    // 程式碼
    system("PAUSE");
    return
#ifndef _MSC_VER
    EXIT_SUCCESS
#endif
    ;
}

WinMain

編輯
 
這是一段WinMain的程式碼。

微軟視窗為基礎的程式設計上,WinMain[4]函式是視窗程式的進入點,函式原型如下所示:

int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow);

.Net 語言(C#、VB 等)

編輯

C#編寫的程式,在開始執行時CLR會先去尋找帶有.entrypoint IL標示的靜態方法,而這個靜態方法可能沒有參數,或是只有單一string[]型態的參數,而且還有void或是int型態的傳回值,找到後才會執行這個方法,而這個方法就是主函式。[5]

static void Main();
static void Main(string[] args);
static int Main();
static int Main(string[] args);

指令列參數會被引入到args變數內,引入的方式與Java相類似。但是,針對有整數傳回值的Main而言,引入的方式類似C/C++,而指令列參數會被當成處理程序的結束狀態,傳回給作業系統或是執行它的外部環境。

同為 .net 語言的 Visual Basic .NET 大體也是一樣。不過不同的是,舊版本 Visual Basic 的程序可以選擇在執行默認初始化步驟後以一個窗體啟動,此時的主函數是不可見的;新版本為了兼容性和簡化編碼工作而保留了這個特性。

Java程式語言是以main 方法來當做程式開始的起點,方法如下:

public static void main(String[] args)

命令列指定參數是args。如同C和C++一樣,「main」也是唯一的。Java的main方法無任何的傳回值。

Pascal

編輯

Pascal的主要程序是不需命名的。因為Pascal程式的程序和函式在編寫程式上比C、C++或是Java更加嚴格,在程式裡主要程序通常才是最後的程序。Pascal沒有main或是其他相類似的關鍵字。

以下是Hello world範例:

procedure hello() begin
  writeln('Hello world')
end;
begin
  hello()
 end.

Pike與C/C++的語法相類似。從main開始執行。「argc」代表環境參數的個數。「argv」代表環境參數的值。

舉例如下:

int main(int argc, array(string) argv)

參見

編輯

參考資料

編輯
  1. ^ Wagner, Bill. Main() / Entry Points (C# Programming Guide) - Microsoft Developer Network. docs.microsoft.com. 2017-08-01 [2018-12-03]. (原始內容存檔於2020-11-11) (美國英語). 
  2. ^ argv: the vector term in this variable's name is used in traditional sense to refer to strings.(基本上這個參數是以傳統的方法對參數的字串進行存取的動作,相當於指標陣列)
  3. ^ The char *apple Argument Vector. [2009-10-28]. (原始內容存檔於2015-12-22). 
  4. ^ 存档副本. [2009-10-28]. (原始內容存檔於2018-08-21). 
  5. ^ 存档副本. [2009-11-04]. (原始內容存檔於2008-02-04). 

外部連結

編輯