詳解C語(yǔ)言預(yù)處理器

C預(yù)處理器在預(yù)處理器在源代碼編譯之前怕膛,對(duì)其進(jìn)行一些文本性質(zhì)的操作,它的主要任務(wù)包括:

  • 刪除注釋焕盟;
  • 插入被#include指令所包含的的文件內(nèi)容铝阐;
  • 定義和替換由#define指令定義的符號(hào);
  • 確定代碼的部分內(nèi)容是否應(yīng)該根據(jù)一些條件編譯指令進(jìn)行編譯删壮;

預(yù)定義符號(hào)

下表總結(jié)了預(yù)處理器定義的符號(hào)贪绘,它們的值是字符串常量或是十進(jìn)制數(shù)字常量

符號(hào) 樣例值 含義
FILE "name.c" 進(jìn)行編譯的文件名
LINE 25 文件的當(dāng)前行號(hào)
DATE "jan 31 1997" 文件被編譯的日期
TIME "18:04:30" 文件被編譯的時(shí)間

define

#define的一般形式如下:

#define name staff

有了這條指令央碟,每當(dāng)有符號(hào)name出現(xiàn)在這條指令后面時(shí)税灌,預(yù)處理器就會(huì)把它替換成staff.

替換文本并不僅限于數(shù)值字面常量。#define指令亿虽,可以把任何文本替換到程序中菱涤,下面有幾個(gè)例子。

#define reg register
#define do_forever for(;;)
#define CASE break;case

如果定義中的staff非常長(zhǎng)洛勉,它可以分成幾行粘秆,除了最后一行之外,每行都要加上一個(gè)反斜杠(\),如下面的例子:

#define DEBUG_PRINT printf("File % line %d:"\
                           "x=%d,y=%d,z=%d",\
                            __FILE__,__LINE__,\
                             x,y,z)

#define機(jī)制包括了一個(gè)規(guī)定收毫,允許把參數(shù)替換到文本中攻走,這種實(shí)現(xiàn)通常稱為定義宏殷勘,下面是宏的定義方式:

#define  name(parameter_list)  stuff
  • 參數(shù)列表的左括號(hào)必須與name緊鄰,如果兩者之間出現(xiàn)空白昔搂,列表參數(shù)就會(huì)被解釋為stuff的一部分玲销。
  • stuff每個(gè)參數(shù)加上括號(hào)以及整個(gè)stuff加上括號(hào)避免引起歧義,如下:
define  DOUBLE(x)  ((x)+(x))

函數(shù)與宏

宏的優(yōu)點(diǎn)或缺點(diǎn):

優(yōu)點(diǎn):

  • 使用宏比使用函數(shù)在程序的規(guī)模速度方面更勝一籌摘符;
  • 宏與類型無(wú)關(guān)贤斜;
  • 使用宏可以完成函數(shù)無(wú)法完成的操作;

缺點(diǎn):

  • 每次使用宏逛裤,一份宏定義的代碼的拷貝都將插入到程序中——除非宏非常短瘩绒,否則使用宏大幅度增加程序的長(zhǎng)度;
 /*宏與類型無(wú)關(guān)的例子*/
#define  MAX(a,b)  ((a) > (b) ? (a) : (b)) 
/*使用宏可以處理函數(shù)無(wú)法處理的例子*/
#define  MALLOC(n,type)  ((type*)malloc((n) * sizeof(typpe)))

undef

這條指令用于移除一個(gè)别凹,使用形式如下:

#undef name

如果一個(gè)現(xiàn)存的名字需要被重新定義草讶,那么它的就定義必須使用#undef移除洽糟。

條件編譯

在編譯的過(guò)程中炉菲,如果我們可以選擇某條語(yǔ)句或某組語(yǔ)句進(jìn)行翻譯或忽略將會(huì)很方便,條件編譯能夠很好的滿足上述假想坤溃,有兩種條件編譯的形式:

  • 第一種形式:
#if  constant-expression 
  statements
#endif
  • 第二種形式:
#if  constant-expression 
  statements
#elif  constant-expression 
  other statements...
#else
  other statements
#endif
  • constant-expression 常量表達(dá)式(字面值常量或是#define定義的符號(hào))拍霜,由預(yù)處理器進(jìn)行求值;
  • 如果constant-expression為真薪介,那么statemens被正常編譯祠饺,否則被忽略;
  • elif的個(gè)數(shù)沒(méi)有限制汁政,每個(gè)constant-expression 只有當(dāng)前面所有的常量表達(dá)式的值都為假時(shí)才會(huì)被編譯道偷,#else子句中的語(yǔ)句只有當(dāng)前面的所有常量表達(dá)式的值都為假時(shí)才被編譯,其它情況下都被忽略记劈。

是否被定義

測(cè)試一個(gè)符號(hào)是否被定義也是可能的勺鸦,它的使用形式如下:

  • 第一組等價(jià)形式:
#if defined(symbol)
#ifdef symbol
  • 第二組等價(jià)形式:
# if !defined(symbol)
#ifndef symbol

嵌套指令

條件編譯的指令可以相互嵌套,如下:

#if defined(OS_UNIX)
    #ifdef OPTION1
      unix_version_of_option1();
    #endif
    #ifdef OPTION2
      unix_version_of_option2();
    #endif
#elif defined(OS_MDOS)
    #ifdef OPTION2
          msdos_version_of_option2();
   #endif
#endif

文件包含

#include指令使另一個(gè)文件的內(nèi)容被編譯目木,這種替換的方式很簡(jiǎn)單:預(yù)處理器首先將這些指令刪除换途,并用包含的內(nèi)容取而代之,一個(gè)頭文件被包含了多少次就實(shí)際被編譯了多少次刽射。

函數(shù)庫(kù)文件的包含

函數(shù)庫(kù)文件的包含使用下面的語(yǔ)法:

#include <filename>

本地文件包含

本地庫(kù)文件的包含使用下面的語(yǔ)法:

#include "filename"

處理本地頭文件的一種策略就是在源文件所在的當(dāng)前目錄進(jìn)行查找军拟,如果該頭文件未找到,編譯器就像查找函數(shù)庫(kù)頭文件一樣在標(biāo)準(zhǔn)位置查找本地頭文件誓禁。

嵌套文件包含

多重包含在絕大多數(shù)情況下出現(xiàn)于大型程序中懈息,他往往需要使用很多頭文件,避免多重包含可以使用下面這種編寫(xiě)方式來(lái)編寫(xiě)頭文件

#ifndef _HEADERNAME_H
#define _HEADERNAME_H
/*
*All the stuff that you want in the header file
*/
#endif

當(dāng)頭文件第一次被包含時(shí)摹恰,它正常處理辫继,再次包含阁最,它的所有內(nèi)容被忽略。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末骇两,一起剝皮案震驚了整個(gè)濱河市速种,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌低千,老刑警劉巖配阵,帶你破解...
    沈念sama閱讀 206,839評(píng)論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異示血,居然都是意外死亡棋傍,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,543評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門难审,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人告喊,你說(shuō)我怎么就攤上這事∏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 153,116評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵秆吵,是天一觀的道長(zhǎng)淮椰。 經(jīng)常有香客問(wèn)我,道長(zhǎng)主穗,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,371評(píng)論 1 279
  • 正文 為了忘掉前任忽媒,我火速辦了婚禮,結(jié)果婚禮上爷肝,老公的妹妹穿的比我還像新娘猾浦。我一直安慰自己,他們只是感情好灯抛,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,384評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著对嚼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪漠烧。 梳的紋絲不亂的頭發(fā)上杏愤,一...
    開(kāi)封第一講書(shū)人閱讀 49,111評(píng)論 1 285
  • 那天珊楼,我揣著相機(jī)與錄音,去河邊找鬼度液。 笑死,一個(gè)胖子當(dāng)著我的面吹牛已慢,可吹牛的內(nèi)容都是我干的霹购。 我是一名探鬼主播佑惠,決...
    沈念sama閱讀 38,416評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼膜楷,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了把将?” 一聲冷哼從身側(cè)響起忆矛,我...
    開(kāi)封第一講書(shū)人閱讀 37,053評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤请垛,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后宗收,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,558評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡混稽,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,007評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了匈勋。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,117評(píng)論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡痘系,死狀恐怖饿自,靈堂內(nèi)的尸體忽然破棺而出汰翠,到底是詐尸還是另有隱情,我是刑警寧澤健田,帶...
    沈念sama閱讀 33,756評(píng)論 4 324
  • 正文 年R本政府宣布佛纫,位于F島的核電站,受9級(jí)特大地震影響雳旅,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜攒盈,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,324評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望僵蛛。 院中可真熱鬧迎变,春花似錦充尉、人聲如沸衣形。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,315評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)句狼。三九已至笋熬,卻和暖如春腻菇,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筹吐。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,539評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蔬捷,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,578評(píng)論 2 355
  • 正文 我出身青樓周拐,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親审丘。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,877評(píng)論 2 345

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