簡體   English   中英

C 中 main() 的函數聲明和定義

[英]Function Declaration & Definition in C for main()

我研究並理解在 C 中創建或編寫函數的標准方法是:

function declaration - declare the function name, arguments, and return value
function definition - define the function with the actual code implementation
function call - call or invoke the function with the name and arguments

C 中的函數main()是一個特殊的函數名稱,它指示您的程序從哪里開始,是您編寫的 C 源代碼在程序中的入口點。 C 標准運行時的一部分是需要知道您正在編寫的 C 程序從何處開始的入口點。 這用函數名main()表示。

首先,您必須了解 C 編譯器將 C 源代碼文本轉換為二進制目標文件。 然后將這些二進制對象文件與其他二進制對象文件鏈接在一起以生成實際的可執行程序。 這些類型的二進制目標文件之一是庫文件,其中包含一個或多個函數的二進制代碼,這些函數先前已編譯並組合到單個文件中。

C 編譯器附帶幾個庫文件,其中包含完成可執行程序所需的功能。 其中之一是編譯器的 C 運行時。

當您的可執行程序啟動時,它不會從main()開始。 相反,它從 C 運行時中的一個特殊位置開始,該位置為您的可執行文件設置運行時環境,然后調用您提供的main()函數。 main()函數是您的源代碼開始的地方。

作為 C 編譯器的一部分,還有一個包含文件,例如#include <stdio.h>等。 這些包含文件包含 C 標准庫函數的聲明,例如printf()函數。

因此在 C 編譯器中為您聲明了main()函數,但是您必須提供函數的實際定義。

由於main()是一個外部標簽,因此您只能定義一個名為main()的函數。 如果您有多個main()定義,那么當鏈接器嘗試將您的二進制對象文件鏈接到一個可執行文件中時,它將看到多個main()函數並發出錯誤,因為它不知道該使用哪一個。

一種思考方式是:(1) C 編譯器提供main()的聲明,(2) 你提供main()的定義,(3) C 運行時調用你的函數main()作為啟動的一部分啟動你的程序。

另請參閱- 1)預處理器,鏈接器,2)頭文件,庫之間有什么區別? 我的理解正確嗎?

main()的函數定義

C 的標准為main()指明了兩種不同的聲明: int main(int argc, char *argv[])int main(void) (參見ISO/IEC 9899:TC3 草案中的第 5.1.2.2.1 節程序啟動) . 另請參閱int argc, char *argv[] 是什么意思? . 另請參閱C 和 C++ 中的 main() 應該返回什么? .

一些 C 編譯器還可能提供其他替代方案,包括寬字符接口,例如int wmain(int argc, wchar_t *argv[]) (參見C++ 中的 WINMAIN 和 main() (Extended) )。 C++ 編譯器可能允許int main(int argc, wchar_t *argv[])因為 C++ 允許函數重載,而 C 不允許。 根據目標程序是控制台應用程序還是 GUI,Microsoft C++ 編譯器有多種main()替代方案。

使用main()的返回值的正常方式是,如果成功則返回 0 值,如果出現錯誤則返回非零正數。 這是原始 Unix 環境中的正常和可接受的行為,其中程序從命令行在終端窗口中運行(參見Wikipedia 主題 Bourne ShellWikipedia 主題 Bash以及Returning value from called function in a shell script其中包含一些示例腳本),並且大多數程序都與命令 shell 腳本一起使用。

一些程序使用返回值來指示某種測試的結果。 在這些情況下, main()返回的值既不是成功代碼也不是錯誤代碼,而是返回值指示腳本可以測試的某些條件,作為執行其目的的一部分。 例如,從傳感器查詢空氣質量指示的程序可能會返回三個不同的值,指示好、一般或差,然后腳本使用這些值來執行某些操作,例如以特定速度打開通風系統風扇。

以下是main()定義的幾個示例:

// usage: mypgm pathname
// Open the specified file and do things with the file's contents.
//
// program expects a single command line argument specifying a file.
// if pathname is not specified then it's an error.
int main(int argc, char *argv[])
{
    // there is always one argument as the first argument is always
    // the program name. Any additional arguments added to the
    // command line begin with the second argument.
    //    argv[0]  -> program or command name
    //    argv[1]  -> expecting a pathname to be specified
    if (argc < 2) {
        printf ("Filename not specified\n");
        return 1;    // return non-zero indicating an error
    }

    // source code to do stuff with the specified file

    return 0;     // return zero indicating no error
}

// usage: mypgm 
//
// program does not expect any command line arguments and if any are
// specified the arguments are ignored.
//
int main (void)
{
    // source code to do stuff 
    return 0;
}

// usage: mypgm 
//
// program does not expect any command line arguments and if any are
// specified the arguments are ignored.
//
// the following definition also compiles.
int main ()
{
    // source code to do stuff 
    return 0;
}

在 C 中,您可以遞歸調用 main。 您不得在沒有定義的情況下聲明 main。

"

C語言標准n1256

5.1.2.2.1 程序啟動

1 程序啟動時調用的函數名為main。 實現沒有聲明這個函數的原型。 它應定義為返回類型為 int 且不帶參數:

 int main(void) { /* ... */ }

或者帶有兩個參數(這里稱為 argc 和 argv,盡管可以使用任何名稱,因為它們是聲明它們的函數的局部變量):

 int main(int argc, char *argv[]) { /* ... */ }

或等價物;9) 或以其他一些實現定義的方式。

在 C 中,編譯器必須知道函數的返回類型和參數列表(如果有),然后才能翻譯函數調用

函數定義也用作它的聲明 如果在同一個翻譯單元中調用函數之前定義函數,則不需要為它編寫單獨的聲明:

void foo ( void ) // definition, also serves as declaration
{
  ...
}

void bar( void )
{
  ...
  foo();   // call
  ...
}

由於我們在foobar調用之前定義了它,編譯器已經知道foo的返回類型和參數列表,所以我們不需要在bar調用之前再次聲明 但是,如果我們要在bar之后定義foo ,或者如果foo在單獨的翻譯單元(源文件)中定義,那么我們需要bar調用之前單獨聲明:

void bar( void )
{
  void foo( void ); // declaration
  ...
  foo( ); // call
}

void foo( void ) // definition
{
  ...
}

main的特殊之處在於通常不需要在代碼中單獨聲明它; 您通常不會顯式調用main 它通常由運行時環境調用,它已經期望main返回一個int並采用零或兩個參數,如下所示:

int main( void );
int main( int, char ** );

實現可以為main提供額外的簽名,他們必須記錄這些簽名。

關於我看到有人明確稱為main的唯一地方是在IOCCC 我從未在生產代碼中看到過有效的用例。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM