C之main函數和命令行參數(三十)

        我們知道在 C 語言中,程序是從 main 函數開始運行的,我們稱其爲主函數。我們來看看下面幾種 main 函數定義正確嗎?


圖片.png

        那麼 main 函數的原型到底是什麼呢?我們來看看編譯器怎麼說,我們分別編譯下四種 main

 函數的形式,經過編譯後,程序可以編譯通過並且執行完成。那麼最標準的 main 函數的原型是上面的第四種,main 函數是操作系統調用的函數,操作系統總是將 main 函數作爲應用程序的開始並且將 main 函數的返回值作爲應用程序的退出狀態。那麼 C 編譯器爲什麼要支持這麼多不同的 main 函數原型呢?我們來做個實驗,代碼如下

#include <stdio.h>

int main()
{
    printf("hello\n");
    
    return 99;
}

        我們在 BCC 編譯器下編譯看看,結果肯定是打印 hello 了。但是我們返回的是 99,我們順便打印下環境變量的值,看看有什麼玄機

圖片.png

        我們看到打印的環境變量的值爲 99。如果我們將上面程序中的 return 後面改成 0。再來編譯看下環境變量的值是多少

圖片.png

        我們看到環境變量的值變成 0 了。那麼 main 函數的返回值是將它返回到系統中並保存下來。那麼回到我們之前所說的問題,在以前的程序中,好多中編程寫法。我們爲了兼容以前所有的程序,編譯器就必須得支持所有的 main 函數的寫法。那麼程序執行時可以向 main 函數傳遞參數,格式:int main(int argc, char *argv[], char *env[])a> argc - 命令行參數個數;b> argv - 命令行參數數組;c> env - 環境變量數組;我們平時見到的大多數是帶前兩種的 main 函數的寫法。

        那麼在gcc編譯器中,常見用法如下:

圖片.png

        我們下來看個示例代碼,代碼如下

#intclude <stdio.h>

int main(int argc, char* argv[], char* env[])
{
    int i = 0;
    
    printf("============== Begin argv ==============\n");
    
    for(i=0; i<argc; i++)
    {
        printf("%s\n", argv[i]);
    }
    
    printf("============== End argv ==============\n");
    
    return 0;
}

        我們來看看編譯效果

圖片.png

        我們可以看到打印出了 ./a.out。也就是說打印出了除過 gcc 以外的命令行參數,我們再以下面這種方式來打印呢

圖片.png

        那麼我們可以看到打印出了除 gcc 以外的所有參數。講到最後,我們再來討論個有意思的問題:main 函數一定是程序執行的第一個函數嗎?咋一聽,就是啊,我們平時書上所見到的,還有老師說的都是這樣的哈。那麼我們來做個實驗,代碼如下

#include <stdio.h>

#ifndef __GNUC__
#define __attribute__(x) 
#endif

__attribute__((constructor))
void before_main()
{
    printf("%s\n",__FUNCTION__);
}

__attribute__((destructor)) 
void after_main()
{
    printf("%s\n",__FUNCTION__);
}

int main()
{
    printf("%s\n",__FUNCTION__);
    
    return 0;
}

        我們看到如果是 GUNC 編譯器的話,便定義 __attribute__ 宏。通過這個宏,我們分別聲明瞭兩個函數,我們來看看編譯結果

圖片.png

        我們看到竟然在 main 函數的前後分別執行了這兩個函數。感覺很神奇,那麼這個 __attribute__ 宏便是我們 gcc 編譯器所特有的屬性關鍵字。使用就可以在 main 函數的執行前後再去執行別的函數。我們再來看看在 BCC 編譯器中,它還支持嗎

圖片.png

        我們看到它不支持那個 __FUNCTION__ ,我們便將他換成對應的字符串。編譯後的結果是隻打印了 main,也就是說它在 main 函數前後並沒有去執行那兩個函數。所以這個特性也是編譯器特有支持的,但起碼說明了在現代編譯器中支持在 main 函數前調用其他函數


        歡迎大家一起來學習 C 語言,可以加我QQ:243343083

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章