關於標頭檔案是否參與編譯的討論

2021-07-04 06:24:23 字數 2114 閱讀 3565

問題就是。。。

標頭檔案是否真正參與編譯?

.h的內容被插入到.c中,作為.c的內容被編譯。.h檔案本身不直接參加編譯。

據我理解,這句話就是說明了標頭檔案不直接參與編譯,是作為乙個插入來理解。

也就是說:

是要編譯的,只不過這些標頭檔案是預編譯的。每個原始檔包涵的標頭檔案都會被預編譯包含到原始檔中去。

這樣就又牽出來三個子問題~~

預編譯是什麼?

網上的答案大致理解為類似複製貼上的操作,這樣理解是有理由的,因為

(1)標頭檔案不一定是 .h 檔案,可以是任意型別

(2)標頭檔案可以定義一些很奇怪的東西,見下面的**

// testheadcompile.h

1, 2, 3, 4, 5

#include

using

namespace

std;

int main()

; cout

<1]

0;}

分析:這段**可以說是真的**,因為標頭檔案寫在了函式體內,這麼說的確就像是乙個複製貼上,關鍵是可以跑出結果,我在vs2012 release模式下,結果如下:

而且還被360誤認為是木馬。。。

於是我這樣認為:如果需要什麼東西(變數或者方法)的時候,就直接可以像利用 #define 一樣用 #include 了?而且#include,有井號本身就是巨集的寫法~~

但是發現,把 include 像上面一樣寫在方法體內,定義變數可以,函式不行,否則會報「本地函式定義是非法的」的錯,但如果 include 在開頭,就可以正常使用函式。這又是乙個預處理的典型代表,說明了在函式裡面定義了函式~~~

其實甚至可以寫出這種鬼畜的**:

// testheadcompile.h

1, 2, 3, 4

#include

using

namespace

std;

int main()

; cout

<4]

0;}

答案是5

既然上面說是預編譯,或者說是單純的複製,那麼那些沒有實現的函式預編譯?編譯?鏈結的時候編譯器怎麼做的?那些實現了,在整個過程沒有用到的函式呢???

這個問題,我是這樣看的:

所有的編譯都是單獨的,沒有實現的函式,就沒有單獨實現的編譯,如果用到了,找不到實現體,就會報鏈結錯誤,也就是vs裡面常見的「fatal error lnk***: n 個無法解析的外部命令」。。。

而對於標頭檔案的作用僅僅是為了在編譯的時候告訴編譯器,這裡如果用到一些其他檔案的東西,我實現了,編譯別報錯!

既然說沒有參與編譯,只是參與預編譯,但是可以在標頭檔案裡面定義函式,又如何解釋?

首先我來回答一下這個問題,個人感覺是參與編譯的,但是是標頭檔案被包含到原始檔進行編譯,也就是說編譯器只會編譯原始檔,不被包含的標頭檔案是沒有存在的意義的,因為我故意把頭檔案寫錯,然後這樣報錯。。。

剛剛測試發現了乙個現象,沒有cpp檔案,vs也可以編譯,我懷疑在編譯的時候,預設將main函式所在的檔案作為編譯檔案,即使main函式寫在標頭檔案,也可以正常執行。

而在linux下面,用編譯器編譯時需要指定編譯的檔案,所以有沒有字尾名是無關緊要的,反正都是文字檔案,讀取方式就是確定的,所以linux對於字尾名並不重要。

關於 pch 預編譯標頭檔案

預編譯標頭檔案 預編譯標頭檔案 一般擴充套件名為.pch 是把乙個工程中較穩定的 預先編譯好放在乙個檔案 pch 裡.這些預先編譯好的 可以是任何的c c 甚至可以是inline函式,只它們在整個工程中是較為穩定的,即在工程開發過程中不會經常被修改的 為什麼需要預編譯標頭檔案?一言以蔽之 提高編譯速...

關於VC 的標頭檔案

以下出自 effective c 懾於被激怒的程式設計師會產生的破壞力,標準 委 員會決定為包裝了std的那部分標準庫構件建立新的頭檔名。生成新標頭檔案的方法僅僅是將現有c 頭檔名中的 h 去掉,方法本身不重要,正如最後產生的結果不一致也並不重要一樣。所以變成了,變成了,等等。對於c頭 檔案,採用同...

關於預編譯標頭檔案的一些知識

許多初學 vc 的朋友也許都為那麼乙個問題困擾過 為什麼所有的 cpp 都必須 include stdafx.h 也許請教了別的高手之後,他們會告訴你,這是預編譯標頭檔案,必須包含。可是,這到底是為什麼呢?預編譯頭有什麼用呢?這得從頭檔案的編譯原理講起。其實標頭檔案並不神秘,它的全部作用,就是把自己...