我從一輩子下來就呆在這個昏暗的地方。linux
我不明白爲何程序員這麼喜歡 Dark Mode,Brighten Mode 纔是個人最愛。據說最近連 iphone 都開始支持 Dark Mode 了,沒話講。。。說好的毫不妥協呢?c++
我周圍是熙熙攘攘的函數羣,穿插着變量聲明和宏定義。程序員
在咱們這裏,函數是一等公民。express
固然,不光在 C++,在面向過程的 C 語言、面向對象的 Java ,尤爲是在那些函數式編程的語言裏,咱們都扮演着舉足輕重的角色。編程
能力越大,責任越大。我和一羣函數夥伴們就負責維護着程序的功能。每一個函數的一小步,合起來就是功能模塊的一大步。windows
做爲一門靜態編譯型語言,咱們不像那些解釋語言同樣,寫完就能直接運行,而是要先通過編譯這一道坎,成爲機器語言,纔可以運行在咱們賴以生存的機器上。iphone
這道坎不是那麼好過的,再頂尖的程序員,也會在這上面栽跟頭。函數式編程
放在往常,雖然程序偶爾會出 bug ,但你們齊心合力,可謂蟲(bug)擋殺蟲,過五關斬六將,整個程序也稱得上是層次分明。函數
但此次,咱們遇到了大問題。調試
今天的一切看起來都很平凡,至少我是這麼認爲的。
屏幕外的程序員像日常同樣敲着代碼,咱們像日常迎接着新函數的到來,像日常同樣嬉笑怒罵,像日常同樣期待着預編譯進程的到來。
預編譯進程是整個編譯進程的先鋒。
像往常同樣,咱們從磁盤出發,沿着總線來到了內存。這裏就是進程的工做車間。
預編譯進程第一步會 刪除全部 #define
,展開宏定義。處理條件預編譯指令。
#define WINDOWS #define BUFSIZE 1024 #define DEPTH 4 #define DECODE "utf-8" ...
上面的就是宏定義,每次咱們都要在預編譯進程的指揮下,把語句裏出現的宏替換成對應的值。
這一步其實原本不須要咱們乾的,程序員怕麻煩,想要作到「一處修改,到處更改」,就發明了宏定義,讓編譯器來幹這些「髒活累活」。
處理條件預編譯指令就有點不同了:
//windows or linux #ifdef WINDOWS <experssion1> #else <experssion2> #endif
若是宏定義有這個 WINDOWS
,就只留下 <experssion1>
,沒有的話就留 <experssion2>
。說白了,就是個預編譯階段能執行的 if... else ...
語句。上面的語句一處理,就變成了:
<experssion1>
對,註釋也會被刪除。
可憐那些註釋,這一生都未曾領略 CPU 裏的風景。
第二步是處理 #include
預編譯指令。
這一步就比上面的複雜多了。用專業的話來講,處理 「#include 」預編譯指令,就是將被包含的文件插入到該預編譯指令的位置。這個過程是遞歸進行的,也就是說被包含的文件可能還包含其餘文件。
#include "config.h" <expressions>
別看他們如今就只有短短兩句,等把 config.h
文件內容複製過來,信息量一會兒就大了。
#ifndef _CONFIG_H_ #define _CONFIG_H_ #define VERSION "1.0.0" #define MODE 1 ... ... #endif <expressions>
補充一句,這個 .h
後綴的傢伙,叫頭文件。他是咱們與其餘文件的函數公民的溝通渠道。
頭文件這個傢伙和源文件不太同樣,他是包含功能函數、數據接口聲明的載體文件,主要用於保存程序的聲明。也就是說,頭文件裏是沒有函數的——咱們曾屢次試圖佔領頭文件的領地,但都沒有成功——都是由於程序員的約束。
每一個頭文件都會帶有一組條件預編譯語句,用來防止本身被屢次編譯。
至於怎麼作到的,這太簡單了,我不說你也能想出來。
據說有的編譯器還支持 #pragma once
,添在頭文件第一行就能作到相同的事情。惋惜咱們的編譯器有點舊,不兼容他們。
最後這步就比較快了,添加行號和文件名標識。
走到這裏,咱們已經獲得了編譯器調試的須要的行號信息,若是編譯到哪一步出錯,或者出現 warning
這樣的警告,就能把行號顯示出來,方便程序員及時發現問題源頭。
今天的預編譯比我想象中要快一點,可能此次沒什麼進程跟咱們搶 CPU 資源吧。
預編譯階段結束,#
的數量大大減小,僅剩下幾個 #pragma
指令留在這裏。
和其餘宏定義指令不同的是,#pragma
是可以跟編譯器分庭抗禮的存在,預編譯進程見了都得避讓三分。
#pragma warning( disable: 4507 34; once: 4385; error: 164 )
像這條指令,就是專門給編譯器看的,意思是 ‘不顯示4507和34號警告信息 ,4385號警告信息僅報告一次,把164號警告信息做爲一個錯誤’ 。能夠說,她是程序員和編譯器之間的信鴿。
<!--要注意的是,這裏面的第幾步第幾步是不嚴謹的,預編譯沒有劃分這樣的界限-->
對於我來講,預編譯階段是比較輕鬆的,最複雜也只是處理條件預編譯指令——刪除幾行代碼罷了。
未完待續
若是你們對文章有什麼見解和意見,歡迎提出來~