2017-01-30 34 views
2

我正在使用Gnu cc編譯器Gcc來編譯我的C程序。考慮一個程序,預處理器行由預處理器處理時會發生什麼? - '.i'文件

#include <stdio.h> 
int main(){ 
    return 0; 
} 

現在,當我預處理使用上面的代碼,

cpp sample.c > sample.i 

我得到了很多的內容sample.i我還沒有包括在內。說,'stdio.h'文件是預處理。如果是這樣的話,

問題1:

爲什麼有這麼多的線路在我的預處理文件? I 尚未使用任何標準庫函數和宏。

問題2:

誰能解釋當預處理proccess C文件到底發生了什麼(我在我的 '*。我' 文件得到的內容)

編譯器:GCC

操作系統:Ubuntu的

感謝

+0

它從字面上打開包含文件,並在原地複製內容。如果''還包含其他一些文件,那些文件也會被複制,等等。這就是爲什麼你有這麼多東西,你不認爲你要求。 – BoBTFish

回答

4

爲什麼有這麼多的線路在我預處理文件一個很好的(短)指導?我沒有使用任何標準庫函數和宏。

預處理只是編譯過程的一部分。它或多或少是一個簡單的文本替換,在預處理階段沒有涉及更復雜的事情。預處理器不知道或不在乎您是否在代碼程序中使用了任何標準函數。優化器(作爲編譯過程的一部分)可能會「刪除」不需要的部分。但預處理器不會那樣做。 它會對你包含的所有頭文件和通過頭文件包含的其他頭文件進行預處理,等等。

誰能解釋到底發生了什麼,當預處理過程中的C文件(我在我的「*。我」文件得到的內容)

預處理涉及相當多的任務:宏替換,條件編譯,字符串化,字符串連接等。 您可以詳細瞭解更多關於cpp這裏:https://gcc.gnu.org/onlinedocs/cpp/

3

的preproces sor命令#include "aFile.h"會將來自aFile.h的孔內容放入您的cpp文件中。這正是預處理指令所在的地方。這就是爲什麼您可以使用aFile.h定義的功能的原因。

,如果你是興趣瞭解更多的預處理,對cplusplus.com

+1

爲什麼複製stdio.h文件的內容,雖然我沒有使用任何與它有關的東西(沒有庫函數或宏)? –

+1

預處理器不關心。 – LogicStuff

+1

你還沒有使用它,但你可以。如果你不需要它們,你可以刪除include語句。 – Soeren

1

1)不得使用它們,但你已經在1號線

#include <stdio.h> 

這就是你看到來自哪個包括他們。嘗試將其刪除以查看差異。

2)預處理器讀取您的C文件並處理您聲明的所有預處理器指令。所有預處理器指令都以'#'符號開頭。 '#include'將用給定文件的內容替換這一行。你也有經典的'#ifndef'和'#define'指令。後者等於「if」語句,其允許激活的碼的一部分僅當符號被定義

#ifndef _SOME_SYMBOL_ 
#define _SOME_SYMBOL_ 

#ifndef WIN32 
#include <some_file.h> 
#else 
#include <some_other_file.h> 
#endif 

int main() { return 0;} 

#endif //endof _SOME_SYMBOL_ 

#ifndef _SOME_SYMBOL_ 
#define _SOME_SYMBOL_ 

// this second function is ignored 
int main() { return 0;} 

#endif //endof _SOME_SYMBOL_ 

當預處理器讀取上述文件中,符號「_SOME_SYMBOL_」是未知的,所以預處理器初始化它。接下來它包括文件是否知道WIN32。通常這種符號是通過命令行傳遞的。所以你的代碼的一部分被動態激活或停用。

預處理程序輸出這個

void some_other_function_from_some_other_file(){} 

int main() { return 0;} 
3

預處理程序所做的文本替換。 #include <stdio.h>的淨效應是用<stdio.h>的內容替換#include <stdio.h>行。

實際上,<stdio.h>包含的各種功能的若干聲明的(例如fprintf()fscanf()),變量聲明(例如stdoutstdin),以及一些宏定義(其在後面代碼中使用時,會導致文本替換)。

預處理器被指定爲編譯階段,它將源代碼作爲輸入,根據需要替換文本(例如,我所描述的#include,宏擴展等),並輸出結果源代碼。這輸出你是什麼引導到sample.i

預處理器的輸出是輸入到編譯的稍後階段,這實際上明白聲明,定義,報表等

編譯的階段是順序 - 他們一個接一個地發生,而不是一次全部發生。因此編譯的後期階段沒有任何信息返回到預處理器。編譯的後期階段檢測是否使用了聲明等。但是,由於它不能將這些信息反饋給預處理器(並且預處理器是無法使用這些信息的無知程序),因此預處理器無法知道聲明未被使用並將其過濾掉。