?
Ce document utilise Manuel du site Web PHP chinois Libérer
預(yù)處理器支持文本宏替換和類似功能的文本宏替換。
#define identifier replacement-list(optional) | (1) | |
---|---|---|
#define identifier( parameters ) replacement-list | (2) | |
#define identifier( parameters, ... ) replacement-list | (3) | (since C99) |
#define identifier( ... ) replacement-list | (4) | (since C99) |
#undef identifier | (5) |
#define
指令#define
指令定義的標(biāo)識(shí)符作為一個(gè)宏,即它們指示編譯器替換替換列表標(biāo)識(shí)符的所有連續(xù)出現(xiàn),其可以額外地任選地進(jìn)行處理。如果標(biāo)識(shí)符已經(jīng)被定義為任何類型的宏,那么該程序是格式不正確的,除非定義相同。
類似于對(duì)象的宏將每個(gè)定義的標(biāo)識(shí)符替換為替換列表。#define
指令的版本(1)的行為完全如此。
類似功能的宏將替換列表中的每個(gè)出現(xiàn)的已定義標(biāo)識(shí)符替換為另外的一些參數(shù),然后替換替換列表中任何參數(shù)的相應(yīng)出現(xiàn)。
函數(shù)式宏調(diào)用的語法類似于函數(shù)調(diào)用的語法:宏名稱的每個(gè)實(shí)例后跟一個(gè)(作為下一個(gè)預(yù)處理標(biāo)記引入由替換列表替換的標(biāo)記序列)序列由匹配)令牌終止,跳過中間匹配的左右括號(hào)對(duì)。
參數(shù)的數(shù)量必須與宏定義(參數(shù))中參數(shù)的數(shù)量相同或程序不合格。如果標(biāo)識(shí)符不是功能符號(hào),也就是說本身沒有括號(hào),它根本不會(huì)被替換。
#define
指令的版本(2)定義了一個(gè)簡(jiǎn)單的函數(shù)式宏。
#define
指令的版本(3)定義了一個(gè)具有可變數(shù)量參數(shù)的函數(shù)式宏。可以使用__VA_ARGS__
標(biāo)識(shí)符訪問附加參數(shù),然后使用標(biāo)識(shí)符來替換標(biāo)識(shí)符,然后使用標(biāo)識(shí)符替換它們。
#define
指令的版本(4)定義了一個(gè)類似函數(shù)的宏,其中包含可變數(shù)量的參數(shù),但沒有常規(guī)參數(shù)。只能使用__VA_ARGS__
標(biāo)識(shí)符訪問參數(shù),然后使用標(biāo)識(shí)符替換標(biāo)識(shí)符,并將標(biāo)識(shí)符替換。
注意:如果類似函數(shù)的宏的參數(shù)包含未被左右括號(hào)(如macro(array[x = y, x + 1])
)的匹配對(duì)保護(hù)的逗號(hào),則逗號(hào)將被解釋為宏參數(shù)分隔符,導(dǎo)致由于參數(shù)計(jì)數(shù)不匹配導(dǎo)致的編譯失敗。
#
and ##
operators在函數(shù)式宏中,#
替換列表中的標(biāo)識(shí)符之前的運(yùn)算符通過參數(shù)替換運(yùn)行標(biāo)識(shí)符,并將結(jié)果封裝在引號(hào)中,從而有效地創(chuàng)建字符串文字。另外,預(yù)處理器會(huì)添加反斜杠以避免嵌入的字符串文字(如果有的話)引用,并在必要時(shí)將字符串中的反斜杠加倍。所有前導(dǎo)空白和尾隨空白都被刪除,并且文本中間的任何空白序列(但不在嵌入的字符串文字內(nèi))被折疊為單個(gè)空格。這個(gè)操作被稱為“串化”。如果字符串化的結(jié)果不是有效的字符串,則行為是未定義的。
當(dāng)#在__VA_ARGS__之前出現(xiàn)時(shí),整個(gè)展開的__VA_ARGS__用引號(hào)引起來:#define showlist(...)puts(#__ VA_ARGS__)showlist(); //展開為puts(“”)showlist(1,“x”,int); //展開為puts(“1,\”x \“,int”) | (自C99以來) |
---|
##
在替換列表中的任何兩個(gè)連續(xù)標(biāo)識(shí)符之間的運(yùn)算符運(yùn)行兩個(gè)標(biāo)識(shí)符上的參數(shù)替換,然后連接結(jié)果。這個(gè)操作被稱為“連接”或“令牌粘貼”。只有形成一個(gè)有效令牌的令牌可以被粘貼:形成一個(gè)更長(zhǎng)的標(biāo)識(shí)符的標(biāo)識(shí)符,形成一個(gè)數(shù)字的數(shù)字,或運(yùn)算符,+
并=
形成一個(gè)+=
。評(píng)論不能通過粘貼來創(chuàng)建,/
并且*
因?yàn)樵诳紤]宏替換之前從文本中刪除評(píng)論。如果連接的結(jié)果不是有效的標(biāo)記,則行為是未定義的。
注意:有些編譯器提供了一個(gè)允許##出現(xiàn)在逗號(hào)之后和__VA_ARGS__之前的擴(kuò)展,在這種情況下,當(dāng)__VA_ARGS__非空時(shí),##什么也不做,但當(dāng)__VA_ARGS__為空時(shí)刪除逗號(hào):這使得可以定義宏等fprintf (stderr, format, ##__VA_ARGS__)
。
#undef
directive#undef
指令取消定義標(biāo)識(shí)符,即它通過#define
指令取消標(biāo)識(shí)符的先前定義。如果標(biāo)識(shí)符沒有關(guān)聯(lián)的宏,則該指令被忽略。
任何翻譯單元中都預(yù)先定義了以下宏名稱:
__STDC__ | expands to the integer constant 1. This macro is intended to indicate a conforming implementation (macro constant) |
---|---|
__STDC_VERSION__ (C95) | expands to an integer constant of type long whose value increases with each version of the C standard: 199409L (C95) 199901L (C99) 201112L (C11) (macro constant) |
__STDC_HOSTED__ (C99) | expands to the integer constant 1 if the implementation is hosted (runs under an OS), 0 if freestanding (runs without an OS) (macro constant) |
__FILE__ | expands to the name of the current file, as a character string literal, can be changed by the #line directive (macro constant) |
__LINE__ | expands to the source file line number, an integer constant, can be changed by the #line directive (macro constant) |
__DATE__ | expands to the date of translation, a character string literal of the form "Mmm dd yyyy". The name of the month is as if generated by asctime and the first character of "dd" is a space if the day of the month is less than 10 (macro constant) |
__TIME__ | expands to the time of translation, a character string literal of the form "hh:mm:ss", as in the time generated by asctime() (macro constant) |
199409L
(C95)
199901L
(C99)
201112L
(C11)
(macro constant)
\_\_STDC\_HOSTED\_\_
(C99)
1
如果實(shí)施托管(在 OS 下運(yùn)行),0
則 擴(kuò)展為整數(shù)常量,如果是獨(dú)立的(無 OS 的情況下運(yùn)行)
(macro constant) __FILE__
擴(kuò)展為當(dāng)前文件的名稱,作為字符串文字,可以通過#line 指令進(jìn)行更改
(macro constant) __LINE__
展開為源文件行號(hào),一個(gè)整數(shù)常量,可以通過#line 指令進(jìn)行更改
(macro constant) __DATE__
擴(kuò)展到翻譯日期,形式為 “Mmm dd yyyy” 的字符串文字。月份的名稱如同生成的一樣,如果asctime
月份的日期小于10,則“dd”的第一個(gè)字符是空格
(macro constant) __TIME__
擴(kuò)展到翻譯時(shí),形式為 “hh:mm:ss” 形式的字符串文字,如在 asctime()
(macro constant)
以下附加宏名稱可能由實(shí)現(xiàn)預(yù)定義:
__STDC_ISO_10646__ (C99) | expands to an integer constant of the form yyyymmL, if wchar_t uses Unicode, the date indicates the latest revision of Unicode supported (macro constant) |
---|---|
__STDC_IEC_559__ (C99) | expands to 1 if IEC 60559 is supported (macro constant) |
__STDC_IEC_559_COMPLEX__ (C99) | expands to 1 if IEC 60559 complex arithmetic is supported (macro constant) |
__STDC_UTF_16__ (C11) | expands to 1 if char16_t use UTF-16 encoding (macro constant) |
__STDC_UTF_32__ (C11) | expands to 1 if char32_t use UTF-32 encoding (macro constant) |
__STDC_MB_MIGHT_NEQ_WC__ (C99) | expands to 1 if wide character encoding of the basic character set may not equal their narrow encoding, such as on EBCDIC-based systems that use Unicode for wchar_t (macro constant) |
__STDC_ANALYZABLE__ (C11) | expands to 1 if analyzability is supported (macro constant) |
__STDC_LIB_EXT1__ (C11) | expands to an integer constant 201112L if bounds-checking interfaces are supported (macro constant) |
__STDC_NO_ATOMICS__ (C11) | expands to 1 if atomic types and atomic operations library are not supported (macro constant) |
__STDC_NO_COMPLEX__ (C11) | expands to 1 if complex types and complex math library are not supported (macro constant) |
__STDC_NO_THREADS__ (C11) | expands to 1 if multithreading is not supported (macro constant) |
__STDC_NO_VLA__ (C11) | expands to 1 if variable-length arrays are not supported (macro constant) |
這些宏的值(除了__FILE__
和__LINE__
)在整個(gè)翻譯單元中保持不變。嘗試重新定義或取消定義這些宏會(huì)導(dǎo)致未定義的行為。
預(yù)定義變量__func__(詳見函數(shù)定義)不是預(yù)處理器宏,即使它有時(shí)與__FILE__和__LINE__一起使用,例如通過 assert。 | (自C99以來) |
---|
#include <stdio.h> //make function factory and use it#define FUNCTION(name, a) int fun_##name(int x) { return (a)*x;} FUNCTION(quadruple, 4)FUNCTION(double, 2) #undef FUNCTION #define FUNCTION 34#define OUTPUT(a) puts( #a ) int main(void){ printf("quadruple(13): %d\n", fun_quadruple(13) ); printf("double(21): %d\n", fun_double(21) ); printf("%d\n", FUNCTION); OUTPUT(million); //note the lack of quotes}
輸出:
quadruple(13): 52double(21): 4234million
C11標(biāo)準(zhǔn)(ISO / IEC 9899:2011):
6.10.3宏替換(p:166-173)
6.10.8預(yù)定義的宏名稱(p:175-176)
C99標(biāo)準(zhǔn)(ISO / IEC 9899:1999):
6.10.3宏替換(p:151-158)
6.10.8預(yù)定義的宏名稱(p:160-161)
C89 / C90 標(biāo)準(zhǔn)(ISO / IEC 9899:1990):
3.8.3宏替換
3.8.8預(yù)定義的宏名稱