C++中的預(yù)處理命令言津!學(xué)習(xí)玩耍兩不誤咩~

一攻人、預(yù)處理的由來:?

在C++的歷史發(fā)展中,有很多的語言特征(特別是語言的晦澀之處)來自于C語言悬槽,預(yù)處理就是其中的一個怀吻。C++從C語言那里把C語言預(yù)處理器繼承過來(C語言預(yù)處理器,被Bjarne博士簡稱為Cpp初婆,不知道是不是C Program Preprocessor的簡稱)蓬坡。

二、常見的預(yù)處理功能:?

預(yù)處理器的主要作用就是:??? 把通過預(yù)處理的內(nèi)建功能對一個資源進行等價替換磅叛,最常見的預(yù)處理有: 文件包含屑咳,條件編譯、布局控制和宏替換4種弊琴。?

文件包含:??? #include 是一種最為常見的預(yù)處理兆龙,主要是做為文件的引用組合源程序正文。?

條件編譯:??? #if,#ifndef,#ifdef,#endif,#undef等也是比較常見的預(yù)處理敲董,主要是進行編譯時進行有選擇的挑選紫皇,注釋掉一些指定的代碼慰安,以達到版本控制、防止對文件重復(fù)包含的功能聪铺。?

布局控制:??? #progma化焕,這也是我們應(yīng)用預(yù)處理的一個重要方面,主要功能是為編譯程序提供非常規(guī)的控制流信息铃剔。?

宏替換:??? #define锣杂,這是最常見的用法,它可以定義符號常量番宁、函數(shù)功能元莫、重新命名、字符串的拼接等各種功能蝶押。?

三踱蠢、預(yù)處理指令:?

預(yù)處理指令的格式如下:?

# define tokens

#符號應(yīng)該是這一行的第一個非空字符,一般我們把它放在起始位置棋电。如果指令一行放不下茎截,可以通過反斜杠“/”進行控制,例如:?

???? #define Error?/

???????????????? if(error) exit(1)???

等價于?

???? #define Error if(error) exit(1)

不過我們?yōu)榱嗣阑鹨姼峡话愣疾辉趺催@么用企锌,更常見的方式如下:?

# ifdef __BORLANDC__?

if_true<(is_convertible::value)>::?

template then::type Make;?

# else?

enum { is_named = is_named_parameter::value };?

typedef typename if_true<(is_named)>::template?

then::type Make;?

# endif?

*******************************************************************?

下面我們看一下常見的預(yù)處理指令:?

#define?????????宏定義?

#undef????????? 取消宏?

#include?????? ?文本包含?

#ifdef??????????? 如果宏被定義就進行編譯?

#ifndef???????? ?如果宏未被定義就進行編譯?

#endif?????????? 結(jié)束編譯塊的控制?

#if?????????????? ?表達式非零就對代碼進行編譯?

#else??????????? 作為其他預(yù)處理的剩余選項進行編譯?

#elif????????????? 這是一種#else和#if的組合選項?

#line?????????????改變當前的行數(shù)和文件名稱?

#error??????????? 輸出一個錯誤信息?

#pragma????????為編譯程序提供非常規(guī)的控制流信息?

*******************************************************************?

下面我們對這些預(yù)處理進行一一的說明,考慮到宏的重要性和繁瑣性于未,我們把它放到最后講撕攒。

四、文件包含指令:?

這種預(yù)處理使用方式是最為常見的烘浦,平時我們編寫程序都會用到抖坪,最常見的用法是:?

#include ?????????????file://標準庫頭文件?

#include ??????????file://舊式的標準庫頭文件?

#include "IO.h"?????????????????????file://用戶自定義的頭文件?

#include "../file.h"???????????????? file://UNIX下的父目錄下的頭文件?

#include "/usr/local/file.h"????? file://UNIX下的完整路徑?

#include "..//file.h"??????????????? file://Dos下的父目錄下的頭文件?

#include "http://usr//local//file.h"?? file://Dos下的完整路徑

這里面有2個地方要注意:?

?1、我們用還是??

我們主張使用闷叉,而不是,為什么呢擦俐?我想你可能還記得我曾經(jīng)給出過幾點理由,這里我大致的說一下:?

首先握侧,.h格式的頭文件早在98年9月份就被標準委員會拋棄了蚯瞧,我們應(yīng)該緊跟標準,以適合時代的發(fā)展品擎。?

其次埋合,iostream.h只支持窄字符集,iostream則支持窄/寬字符集孽查。?

還有饥悴,標準對iostream作了很多的改動,接口和實現(xiàn)都有了變化盲再。?

最后西设,iostream組件全部放入namespace std中,防止了名字污染答朋。?

?2贷揽、<io.h>和"io.h"的區(qū)別??

其實他們唯一的區(qū)別就是搜索路徑不同:?

對于#include?? 梦碗,編譯器從標準庫路徑開始搜索?

對于#include?? "io.h" 禽绪,編譯器從用戶的工作路徑開始搜索

五、編譯控制指令:?

這些指令的主要目的是進行編譯時進行有選擇的挑選洪规,注釋掉一些指定的代碼印屁,以達到版本控制、防止對文件重復(fù)包含的功能斩例。?

使用格式雄人,如下:?

1、?

#ifdef?? identifier

your code?

#endif?

如果identifier為一個定義了的符號念赶,your code就會被編譯础钠,否則剔除?

2、?

#ifndef identifier?

your code?

#endif?

如果identifier為一個未定義的符號叉谜,your code就會被編譯旗吁,否則剔除?

3、?

#if?? expression?

your code?

#endif?

如果expression非零停局,your code就會被編譯很钓,否則剔除?

4、?

#ifdef identifier?

your code1?

#else?

your code2?

#endif?

如果identifier為一個定義了的符號董栽,your code1就會被編譯履怯,否則your code2就會被編譯?

5、?

#if??? expressin1?

your code1?

#elif expression2?

your code2?

#else?

your code3?

#enif

如果epression1非零裆泳,就編譯your code1叹洲,否則,如果expression2非零工禾,就編譯your code2运提,否則,就編譯your code3

其他預(yù)編譯指令?

除了上面我們說的集中常用的編譯指令闻葵,還有3種不太常見的編譯指令:#line民泵、#error、#pragma槽畔,我們接下來就簡單的談一下栈妆。?

#line的語法如下:?

#line number filename?

例如:#line 30?? a.h????? 其中,文件名a.h可以省略不寫。?

這條指令可以改變當前的行號和文件名鳞尔,例如上面的這條預(yù)處理指令就可以改變當前的行號為30嬉橙,文件名是a.h。初看起來似乎沒有什么用寥假,不過市框,他還是有點用的,那就是用在編譯器的編寫中糕韧,我們知道編譯器對C++源碼編譯過程中會產(chǎn)生一些中間文件枫振,通過這條指令,可以保證文件名是固定的萤彩,不會被這些中間文件代替粪滤,有利于進行分析。?

#error語法如下:?

#error?? info?

例如:

#ifndef UNIX?

#error This software requires the UNIX OS.?

#endif?

這條指令主要是給出錯誤信息雀扶,上面的這個例子就是杖小,如果沒有在UNIX環(huán)境下,就會輸出This software requires the UNIX OS.然后誘發(fā)編譯器終止怕吴。所以總的來說窍侧,這條指令的目的就是在程序崩潰之前能夠給出一定的信息。?

至于#pragma,我們在解析#pragma指令一文中有過介紹转绷,我們在這里再補充幾句伟件,#pragma是非統(tǒng)一的,他要依靠各個編譯器生產(chǎn)者议经,例如斧账,在SUN C++編譯器中:?

// 把name和val的起始地址調(diào)整為8個字節(jié)的倍數(shù)?

#progma align 8 (name, val)?

char??? name[9];?

double val;?

file://在程序執(zhí)行開始,調(diào)用函數(shù)MyFunction?

#progma init (MyFunction)

預(yù)定義標識符?

為了處理一些有用的信息煞肾,預(yù)處理定義了一些預(yù)處理標識符咧织,雖然各種編譯器的預(yù)處理標識符不盡相同,但是他們都會處理下面的4種:?

__FILE__?? 正在編譯的文件的名字?

__LINE__?? 正在編譯的文件的行號?

__DATE__?? 編譯時刻的日期字符串籍救,例如: "25 Dec 2000"?

__TIME__?? 編譯時刻的時間字符串习绢,例如: "12:30:55"?

例如:cout<<"The file is :"<<__FILE__"<<"! The lines is:"<<__LINE__<

預(yù)處理何去何從?

在淺析C++里面的宏一文中,我們提到了如何取代#include預(yù)處理指令蝙昙,我們在這里就不再一一討論了闪萄。?

C++并沒有為#include提供替代形式,但是namespace提供了一種作用域機制奇颠,它能以某種方式支持組合败去,利用它可以改善#include的行為方式,但是我們還是無法取代#include烈拒。?

#progma應(yīng)該算是一個可有可無的預(yù)處理指令圆裕,按照C++之父Bjarne的話說广鳍,就是:“#progma被過分的經(jīng)常的用于將語言語義的變形隱藏到編譯系統(tǒng)里,或者被用于提供帶有特殊語義和笨拙語法的語言擴充吓妆∩奘保”?

對于#ifdef,我們?nèi)匀皇譄o策耿战,就算是我們利用if語句和常量表達式蛋叼,仍然不足以替代它焊傅,因為一個if語句的正文必須在語法上正確剂陡,滿足類檢查,即使他處在一個絕不會被執(zhí)行的分支里面狐胎。?

最后鸭栖,我們以Bjarne博士的話作為結(jié)尾:“最后,在許多年之后握巢,將Cpp放逐刀程序開發(fā)環(huán)境里晕鹊,與其他附加性語言工具放到一起,那里才是她應(yīng)該呆的地方暴浦〗埃”


“我是一名從事了10年開發(fā)的老程序員,最近我花了一些時間整理關(guān)于C語言歌焦、C++飞几,自己有做的材料的整合,一個完整的學(xué)習(xí)C語言独撇、C++的路線屑墨,學(xué)習(xí)材料和工具。全球最大的C/C++纷铣、編程愛好者的聚集地就在我這里<C語言C++編程學(xué)習(xí)>卵史!歡迎初學(xué)和進階中的小伙伴。希望你也能憑自己的努力搜立,成為下一個優(yōu)秀的程序員以躯。工作需要、感興趣啄踊、為了入行忧设、轉(zhuǎn)行需要學(xué)習(xí)C/C++的伙伴可以跟我一起學(xué)習(xí)!”

關(guān)注我和我的專欄社痛,帶你遨游代碼世界见转!C語言/C++進階之路 - 專題 - 簡書

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蒜哀,隨后出現(xiàn)的幾起案子斩箫,更是在濱河造成了極大的恐慌吏砂,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,826評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件乘客,死亡現(xiàn)場離奇詭異狐血,居然都是意外死亡,警方通過查閱死者的電腦和手機易核,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評論 3 395
  • 文/潘曉璐 我一進店門匈织,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人牡直,你說我怎么就攤上這事缀匕。” “怎么了碰逸?”我有些...
    開封第一講書人閱讀 164,234評論 0 354
  • 文/不壞的土叔 我叫張陵乡小,是天一觀的道長。 經(jīng)常有香客問我饵史,道長满钟,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,562評論 1 293
  • 正文 為了忘掉前任胳喷,我火速辦了婚禮湃番,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘吭露。我一直安慰自己吠撮,他們只是感情好,可當我...
    茶點故事閱讀 67,611評論 6 392
  • 文/花漫 我一把揭開白布奴饮。 她就那樣靜靜地躺著纬向,像睡著了一般。 火紅的嫁衣襯著肌膚如雪戴卜。 梳的紋絲不亂的頭發(fā)上逾条,一...
    開封第一講書人閱讀 51,482評論 1 302
  • 那天,我揣著相機與錄音投剥,去河邊找鬼师脂。 笑死,一個胖子當著我的面吹牛江锨,可吹牛的內(nèi)容都是我干的吃警。 我是一名探鬼主播,決...
    沈念sama閱讀 40,271評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼啄育,長吁一口氣:“原來是場噩夢啊……” “哼酌心!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起挑豌,我...
    開封第一講書人閱讀 39,166評論 0 276
  • 序言:老撾萬榮一對情侶失蹤安券,失蹤者是張志新(化名)和其女友劉穎墩崩,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體侯勉,經(jīng)...
    沈念sama閱讀 45,608評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡鹦筹,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,814評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了址貌。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片铐拐。...
    茶點故事閱讀 39,926評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖练对,靈堂內(nèi)的尸體忽然破棺而出遍蟋,到底是詐尸還是另有隱情,我是刑警寧澤锹淌,帶...
    沈念sama閱讀 35,644評論 5 346
  • 正文 年R本政府宣布匿值,位于F島的核電站赠制,受9級特大地震影響赂摆,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜钟些,卻給世界環(huán)境...
    茶點故事閱讀 41,249評論 3 329
  • 文/蒙蒙 一烟号、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧政恍,春花似錦汪拥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至宗弯,卻和暖如春脯燃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒙保。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評論 1 269
  • 我被黑心中介騙來泰國打工辕棚, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人邓厕。 一個月前我還...
    沈念sama閱讀 48,063評論 3 370
  • 正文 我出身青樓逝嚎,卻偏偏與公主長得像,于是被迫代替她去往敵國和親详恼。 傳聞我的和親對象是個殘疾皇子补君,可洞房花燭夜當晚...
    茶點故事閱讀 44,871評論 2 354

推薦閱讀更多精彩內(nèi)容

  • mean to add the formatted="false" attribute?.[ 46% 47325/...
    ProZoom閱讀 2,696評論 0 3
  • 目錄 一.預(yù)處理的工作方式... 3 1.1.預(yù)處理的功能... 3 1.2預(yù)處理的工作方式... 3 二.預(yù)處理...
    朱森閱讀 1,374評論 0 2
  • C中的預(yù)編譯宏定義 2009-02-10 作者: infobillows 來源:網(wǎng)絡(luò) 在將一個C源程序轉(zhuǎn)換為可執(zhí)行...
    白水灬煮一切閱讀 1,590評論 0 5
  • 作者 謝恩銘,公眾號「程序員聯(lián)盟」(微信號:coderhub)昧互。轉(zhuǎn)載請注明出處挽铁。原文:https://www.ji...
    程序員聯(lián)盟閱讀 2,657評論 3 42
  • ? 預(yù)處理器她紫, 預(yù)處理器并不是編譯器的組成部分,但是它是編譯過程中一個單獨的步驟屿储。簡言之贿讹,C 預(yù)處理器只不過是一個...
    badreisen閱讀 256評論 0 0