有關編譯預處理順序的討論

    衆所周知,程序編譯過程一般分爲預處理,編譯,彙編,鏈接四個過程。而編譯預處理一般主要做3件事:宏擴展,去掉註釋,和合並頭文件。最近遇到了關於宏擴展和合並頭文件執行順序的討論,根據牛人的說法,應該是先合併頭文件,然後開始宏擴展。
    一聽到這個結論的時候,我心裏就產生了疑問,但是因爲當時不確信,就沒有當場質疑“權威”。我心裏的疑問是想象中的這樣一段代碼:

//test1.cpp
#define head <stdio.h>
#include head

int main(){
    printf("test1.cpp/n");
    return 0;   
}

    我在想,如果先合併頭文件,則編譯在開始就會報錯,於是經過上機測試一把,發現居然編譯順利進行,於是我對“權威”的結論表示了質疑,毫無疑問就給他發了一封郵件。不多久,就從“權威”處得到答案。權威到底是權威,不佩服不行,嘿嘿。
    原來,上面的這段代碼可以看作是一個特例,或者說異常。爲什麼這麼說?
include頭文件聲明有三種形式:
1. #include <h-char-sequence> new-line
2. #include "q-char-sequence" new-line
3. #include pp-tokens new-line

    對於第三種(也就是程序test1中使用的方式),C/C++標準是允許的,並且這種格式將會被翻譯成另外的兩種形式。因此,也就是說對於include頭文件時用宏的話會被一開始就執行。但是對於其他更多種使用宏的情況,應該是先合併頭文件,然後再擴展開宏。那麼怎麼能夠證明這一點呢?
    我們再來看一段代碼:

//test2.h
#define head <stdio.h>
//test2.cpp
#include "test2.h"
#include head
int main(){
//....
}

    對於這段代碼,編譯是可以通過的。因爲編譯器首先合併頭文件然後才擴展宏。如果先擴展宏,毫無疑問,在test2.cpp中並沒有head的聲明或定義,因此編譯會失敗;就是因爲先合併了頭文件再擴展宏,程序才能順利編譯成功。
到這裏,我的疑惑也被解決了。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章