第十六章 C 預處理器和 C 庫——《C Primer Plus》筆記

第十六章 C 預處理器和 C 庫

16.1 翻譯程序的第一步

  • 源代碼中的字符映射到源字符集。
  • 編譯器定位每個反斜杠后面跟著換行符的實例赘阀,并刪除它們赎婚。
  • 編譯器把文本化糞池預處理記號序列、空白序列和注釋序列
  • 一個空格替換所有空白序列和注釋序列
  • 開始預處理

16.2 明示常量:#define

指令可以出現(xiàn)在源文件任何地方,其定義從指令出現(xiàn)的地方到文件末尾有效沮尿。

格式:

define 宏 替換列表

有類對象宏,類函數(shù)宏较解。從宏變成最終替換文本的過程稱為宏展開(macro expansion)畜疾。

從技術角度來看,可以把宏的替換體看作是記號型字符串印衔,而不是字符型字符串啡捶,并不是簡單的純文本替換。

16.3 在 #define 中使用參數(shù)

示例:

#define MEAN(X,Y)    (((X)+(Y))/2)

# 運算符

x 是個宏參數(shù)時奸焙,#x 就是轉(zhuǎn)化為字符串 "x" 的形參名瞎暑。稱為字符串化(stringizing)。

#define PSQR(x)    printf("The square of " #x " is %d.\n, ((x)*(x)))

## 運算符

把兩個記號進行拼接組成一個記號

#define XNAME(n)    X##n

變參宏:... 和 VA_ARGS

一些函數(shù)接收數(shù)量可變的參數(shù)与帆。通過把宏參數(shù)列表中最后的參數(shù)寫成省略號來實現(xiàn)這一功能了赌。

#define PR(...)    printf(__VA_ARGS__)

16.4 宏和函數(shù)的選擇

宏函數(shù)優(yōu)點:

  • 執(zhí)行效率更高。
  • 不用擔心變量類型玄糟。

注意點:

  • 宏名中不允許有空格勿她。
  • 用圓括號把宏的參數(shù)和整個替換體括起來。防止運算符優(yōu)先級導致不符合預期的結(jié)果茶凳。
  • 用大寫字母表示宏函數(shù)的名稱嫂拴。提醒該為宏函數(shù)播揪。
  • 如果打算使用宏函數(shù)來加快程序的運行速度贮喧,那么首先要確認使用宏和使用函數(shù)是否會導致較大差異。在程序中值使用一次的宏無法明顯減少程序的運行時間猪狈。

16.5 文件包含:#include

頭文件常用形式:

  • 明示常量
  • 宏函數(shù)
  • 函數(shù)聲明
  • 結(jié)構(gòu)模板定義
  • 類型定義

16.6 其他指令

#undef

取消已定義的 #define 指令

**#ifdef箱沦、#else 和 #endif **

條件編譯

#ifndef

#if 和 #elif

預定義宏

含義
_DATA_ 預處理的預期
_FILE_ 當前源代碼文件名的字符串字面量
_LINE_ 當前源代碼文件中行號的整型常量
_STDC_ 設置為 1 時,表明實現(xiàn)遵循 C 標準
_STDC_HOSTED_ 本即環(huán)境設置為 1雇庙;否則設置為 0
_STDC_VERSION_ 支持 C99 標準谓形,設置為 19990L灶伊;支持 C11 標準,設置為 201112L
_TIME_ 翻譯代碼的時間

_func_ 是預定義標識符寒跳,而不是預定義宏聘萨。

#line

重置 __LINE____FILE__ 宏報告的行號和文件名

#line 10 "cool.c"

#error

讓編譯器發(fā)出一條錯誤消息,該消息包含指令中的文本童太。

#pragma

把編譯器指令放入源代碼中米辐。

C99 還提供 _Pragma 預處理器運算符,把字符串轉(zhuǎn)換成普通的編譯指示书释。

_Pragma("nonstandaertreatmenttypeB on")
/* 等價于 */
#pragma nonstandaertreatmenttypeB on

泛型選擇(C11)

泛型編程(generic programming):指那些沒有特定類型翘贮,但是一旦指定一種類型,就可以轉(zhuǎn)換成指定類型的代碼爆惧。

泛型選擇表達式(generic selection expression):根據(jù)表達式的類型選擇一個指狸页。常和 #define 一起使用。

_Generic(x, int:0, float:1, double:2, defult:3)

類似 switch 語句扯再,根據(jù) x 的類型決定整個表達式的值芍耘。為 int 時值 0,為 float 時值為 1 ...

#define MYTYPE(X) \
_Generic((X), \
    int: "int", \
    float: "float", \
    double: "double", \
    default: "other" \
)

16.7 內(nèi)聯(lián)函數(shù)(C99)

把函數(shù)變成內(nèi)聯(lián)函數(shù)建議盡可能快地調(diào)用該函數(shù)熄阻,其具體效果由實現(xiàn)定義齿穗。

只有具有內(nèi)部鏈接的函數(shù)可以成為內(nèi)聯(lián)函數(shù),因此內(nèi)聯(lián)函數(shù)可能會放到頭文件中饺律。

inline static void eatline(void)
{
  while(getchar() != '\n')
    continue;
}

C 允許混合使用內(nèi)聯(lián)函數(shù)定義和外部函數(shù)定義窃页,不建議如此。

16.8 _Noreturn 函數(shù)(C11)

告訴用戶和編譯器复濒,該函數(shù)不會把控制返回主調(diào)程序脖卖,避免濫用該函數(shù),通知編譯器優(yōu)化一些代碼巧颈。

16.9 C 庫

16.10 通用工具庫

stdlib.h

int atexit (void (func)(void));*

注冊回調(diào)函數(shù)畦木,在程序退出時執(zhí)行。至少可以注冊 32 個函數(shù)砸泛,后進的函數(shù)先執(zhí)行十籍。

void exit (int status)

退出整個程序

  • 刷新所有輸出流
  • 關閉所有打開的流
  • 關閉標準 I/O 函數(shù) tmpfile() 創(chuàng)建的臨時文件。
  • 控制權返回主機環(huán)境唇礁,如果可以的話勾栗,向主機報告終止狀態(tài)。UNIX 程序通常使用 0 表示成功終止盏筐,非零值表示終止失敗围俘。

16.12 斷言庫

void assert (int expression)

接受一個整型表達式作為參數(shù)。如果表達式為假(非零),assert() 宏就在標準錯誤流中寫入一條錯誤信息界牡,并調(diào)用 abort() 函數(shù)終止程序簿寂。

_Static_assert

靜態(tài)斷言。

16.13 string.h 庫中的 memcyp() 和 memmove()

void *memcpy(void* restrict s1, const void* restrict s2宿亡,size_t n)

void *memmove(void *sl常遂,const void *s2,size_t n)

memcopy 假設沒有內(nèi)存重疊挽荠,而 memmove 沒有烈钞。

16.14 可變參數(shù):stdarg.h

創(chuàng)建可變參數(shù)函數(shù)步驟

  • 提供一個使用省略號的函數(shù)原型;
  • 在函數(shù)定義中創(chuàng)建一個 va_list 類型的變量坤按;
  • 用宏把該變量初始化為一個參數(shù)列表毯欣;
  • 用宏訪問參數(shù)列表;
  • 用宏完成清理工作臭脓。
double sum(int lm, ...)
{
  va_list ap;
  double tot = 0;
  int i;
  
  va_start(ap, lim);
  for(i = 0; i < lim; ++i)
    tot += va_arg(ap, double);

  va_end(ap);

  return tot;
}
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末酗钞,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子来累,更是在濱河造成了極大的恐慌砚作,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,941評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件嘹锁,死亡現(xiàn)場離奇詭異葫录,居然都是意外死亡,警方通過查閱死者的電腦和手機领猾,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,397評論 3 395
  • 文/潘曉璐 我一進店門米同,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人摔竿,你說我怎么就攤上這事面粮。” “怎么了继低?”我有些...
    開封第一講書人閱讀 165,345評論 0 356
  • 文/不壞的土叔 我叫張陵熬苍,是天一觀的道長。 經(jīng)常有香客問我袁翁,道長柴底,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,851評論 1 295
  • 正文 為了忘掉前任粱胜,我火速辦了婚禮柄驻,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘年柠。我一直安慰自己凿歼,他們只是感情好,可當我...
    茶點故事閱讀 67,868評論 6 392
  • 文/花漫 我一把揭開白布冗恨。 她就那樣靜靜地躺著答憔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪掀抹。 梳的紋絲不亂的頭發(fā)上虐拓,一...
    開封第一講書人閱讀 51,688評論 1 305
  • 那天,我揣著相機與錄音傲武,去河邊找鬼蓉驹。 笑死,一個胖子當著我的面吹牛揪利,可吹牛的內(nèi)容都是我干的态兴。 我是一名探鬼主播,決...
    沈念sama閱讀 40,414評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼疟位,長吁一口氣:“原來是場噩夢啊……” “哼瞻润!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起甜刻,我...
    開封第一講書人閱讀 39,319評論 0 276
  • 序言:老撾萬榮一對情侶失蹤绍撞,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后得院,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體傻铣,經(jīng)...
    沈念sama閱讀 45,775評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,945評論 3 336
  • 正文 我和宋清朗相戀三年祥绞,在試婚紗的時候發(fā)現(xiàn)自己被綠了非洲。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,096評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡蜕径,死狀恐怖怪蔑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情丧荐,我是刑警寧澤缆瓣,帶...
    沈念sama閱讀 35,789評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站虹统,受9級特大地震影響弓坞,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜车荔,卻給世界環(huán)境...
    茶點故事閱讀 41,437評論 3 331
  • 文/蒙蒙 一渡冻、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧忧便,春花似錦族吻、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,993評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽砍艾。三九已至,卻和暖如春巍举,著一層夾襖步出監(jiān)牢的瞬間脆荷,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,107評論 1 271
  • 我被黑心中介騙來泰國打工懊悯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留蜓谋,地道東北人。 一個月前我還...
    沈念sama閱讀 48,308評論 3 372
  • 正文 我出身青樓炭分,卻偏偏與公主長得像桃焕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子捧毛,可洞房花燭夜當晚...
    茶點故事閱讀 45,037評論 2 355

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