2011-04-20 177 views
21

在C(或基於C語言),一個可以愉快地使用以下語句:#include實際上做了什麼?

#include "hello.h"; 

瞧,在每hello.h函數和變量是自動地使用。

但它實際上做了什麼?我瀏覽了編譯器文檔和教程,並花費了一些時間在線搜索,但我可以對神奇的#include命令形成的唯一印象是它「複製粘貼」hello.h的內容而不是該行。還有更多。

+2

如果有任何安慰,預處理器也可能插入特定於實現的註釋,以便在生成調試信息時獲取行號。如果它實際上具有複製粘貼的效果,則調試器將不知道「真實」源文件和行號。同樣'__FILE__'和'__LINE__'必須在複製粘貼之前被替換。就程序的意義而言,雖然是複製粘貼。 – 2011-04-20 19:24:20

回答

21

從邏輯上說,該複製/粘貼正是發生的情況。恐怕沒有更多了。雖然你不需要;

你的具體例子是由規格所覆蓋,部分6.10.2源文件包含,第3段:

形式的預處理指令

# include"Q-炭 - 序列"新生線

導致用"分隔符之間指定序列標識的源文件的全部內容替換該指令。

5

這(複製/粘貼)正是#include "header.h"所做的。

請注意,#include <header.h>或編譯器無法找到文件"header.h"而它試圖改爲#include <header.h>時將會有所不同。

+1

「不同」只是因爲它通常在不同的地方搜索,並與(標準)庫頭文件在心理上相關聯。 – delnan 2011-04-20 19:13:18

+0

@delnan,根據規範,它們不必有所不同 - 所有搜索都以「實現定義」的方式執行。不同之處在於''''表格如果不起作用,就會回到'<>'表格。 @ pmg是完全正確的。 – 2011-04-20 19:15:43

+0

也是「不同的」,因爲當您執行'#include '時,不需要有一個名爲'「thing.h」'的文件。 – pmg 2011-04-20 19:17:29

0

不是,沒有。編譯器將原始文件描述符保存在堆棧上並打開d文件;當它到達該文件的末尾時,它將關閉它並彈出回原始文件描述符。這樣,它可以幾乎任意地嵌入d文件。

+1

編譯器在gcc中傳遞例如對#include一無所知,因爲它是預處理器傳遞。 – fazo 2011-04-20 19:36:49

+0

@fazo:在大多數情況下,這種區別是沒有意義的。如果你出於某種原因需要學習,我可以去找一個不完整的編譯器列表,以及他們是否使用預處理器。 – geekosaur 2011-04-20 19:38:30

0

的「#包括」的順序聲明「抓住注意」前的 - 處理器(在你的程序實際編譯之前發生的進程)和「告訴」預處理器包含「#include」語句後的任何內容。雖然預處理器可以被告知做了很多事情,但在這個例子中,它被要求識別一個頭文件(在該頭的名稱後面用「.h」表示,表示它是頭)。現在,頭文件是一個包含C聲明和未在代碼中明確定義的函數定義的文件。這是什麼意思?那麼,如果你想使用一個函數或者定義一個特殊類型的變量,並且你知道這些函數/定義是在別處定義的(比如標準庫),那麼你可以包含(#include)你知道包含的頭文件你需要什麼。否則,每次你想使用打印功能(就像你的情況),你必須重新創建打印功能。如果它沒有在你的代碼中明確定義,並且你沒有用你正在使用的函數#include頭文件,你的編譯器會抱怨說:「嘿!我沒有看到這個函數被定義在哪裏,所以我不用'不知道在你的代碼中使用這個未定義的函數是什麼!「。

相關問題