簡體   English   中英

為什么g ++預處理器包含未使用的頭文件

[英]Why g++ pre-processor includes unused header files

我已經創建了兩個頭文件和一個這樣的cpp文件。

cat.h

class Cat
{
};

dog.h

class Dog
{
};

main.cpp中

#include "cat.h"
#include "dog.h"

int main()
{
 Cat my_cat;
 return 0;
}

然后我運行了g++ -E main.cpp >out.cpp命令並生成預處理輸出。 就像這樣。

# 1 "main.cpp"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "main.cpp"
# 1 "cat.h" 1
class Cat
{
};
# 2 "main.cpp" 2
# 1 "dog.h" 1
class Dog
{
};
# 3 "main.cpp" 2

int main()
{
 Cat my_Cat;
 return 0;
}

看了這之后,我想起了幾個疑惑。

  1. 為什么它包含dog.h內容,即使它從未在main.cpp文件中使用過
  2. 在通常的編譯中,在哪里創建這個預處理的臨時文件(在內存或磁盤中)
  3. 每個處理和編譯的順序是什么(首先是每個進程所有文件,然后開始編譯或逐個完成)
  4. 實際的編譯器是否使用#作為注釋的語法

讓我從我所知道的回答:

  1. 因為該文件包含在#include指令中。 就是這樣,沒有對真正使用的內容進行分析。 這種分析通常在SW由人或其他工具重構時完成,而不是由預處理器完成。
  2. 取決於編譯器及其選項。 例如,您可以要求GCC使用管道而不是在文件系統上創建中間文件
  3. 預處理,壓縮,鏈接。 預處理按文件的包含順序完成。 意味着所有包含的文件與源文件一起連接到一個大文件,直到包含樹的末尾。 所有這些都形成了翻譯單元,后來由編譯器編譯。

關於數字4,這不是注釋,這是另一種稱為行控制指令的指令,並告訴編譯器下一段代碼來自哪個文件和行。

編譯器“正確”只能看到翻譯單元 (大致是一個包含所有包含頭文件的源文件,就像你創建的那樣)所以它實際上並不知道有關頭文件的任何信息。 行指令是編譯器知道頭文件中是否有錯誤以及頭文件中的錯誤的方法。

預處理器只對源文件進行文本替換。 所以

#include "dog.h"

簡單地用dog.h的內容dog.h

它不檢查源文件的內容以確定是否正在使用dog.h中的聲明。

預處理(臨時)文件的位置取決於實現。 甚至可能沒有這樣的文件 - 預處理文本可能只是直接從預處理器傳送到另一個執行編譯的可執行文件。

該標准要求實現(編譯器和構建鏈)的行為就像按順序完成多個階段一樣。 一個描述在http://en.cppreference.com/w/cpp/language/translation_phases 但是,實際執行這些階段不需要特定的實現 - 只需要提供結果AS IF。

一般來說,編譯器(在某種意義上只是將預處理代碼作為輸入,並在該鏈接上實現階段7)不需要將#視為注釋。 但是,由於它是在預處理之后調用的,因此實現可以自由執行。 但請注意,預處理器會解釋以#開頭的行,因此會拒絕不恰當地執行的代碼(例如,您嘗試使用#作為注釋標記)。

預處理器不是編譯器。 它不理解C,C ++或任何其他語言。 它所做的只是處理預處理器指令( #... )和一些其他任務,如連接字符串文字。 當然不能刪除死代碼。 死代碼刪除由編譯器或鏈接器完成。

暫無
暫無

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

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