根据N3092(C ++ 11的最终委员会草案),在 16.3:宏替换中,类对象宏定义为:
# define identifier replacement-list new-line
和类似函数的宏定义为:
# define identifier lparen identifier-list_opt ) replacement-list new-line # define identifier lparen ... ) replacement-list new-line # define identifier lparen identifier-list , ... ) replacement-list new-line
全部都有替换列表(所谓的宏值),其定义为:
replacement-list: pp-tokensopt
和 pp令牌定义为:
pp-tokens: preprocessing-token pp-tokens preprocessing-token
和预处理令牌是例如 identifier 。
据我所知,具有空值的宏是定义良好的。
但是, 16.3-3 说:
在类似对象的宏的定义中,标识符和替换列表之间应有空白。
,请注意,替换列表本身是不是可选的(尽管它可以具有空值)。
所以我相信:
//well-formed (function-like macro with value)
#define f(x) (x)<NEWLINE>
//well-formed (function-like macro without value)
#define f(x)<NEWLINE>
//well-formed (function-like macro without value)
#define f(x) <NEWLINE>
//well-formed (object-like macro with value)
#define f hello<NEWLINE>
//**ill-formed** (object-like macro without value)
#define f<NEWLINE>
//well-formed (object-like macro without value)
#define f <NEWLINE>
,因此,例如,所谓的“包含防护”应采用以下形式:
#ifndef is_xyz_included<NEWLINE>
#define is_xyz_included <NEWLINE> // NOTE THE SPACE BEFORE <NEWLINE>
#endif<NEWLINE>
我的解释错误吗?
答案 0 :(得分:15)
我相信您的解释是正确的。因此,有效的包含保护必须具有您所描述的形式,并且带有非换行符的空格。不是换行符,因为
[cpp]
4只能出现在两个字符之间的空白字符 预处理指令中的预处理令牌(从紧接之后 在#之前引入#预处理令牌 终止换行符)是空格和水平制表符 (包括已替换评论或其他可能的空格 翻译阶段3)中的空白字符。
这使得换行符不能成为您提到的段落中讨论的空白。
但是考虑到这个习惯用法在包括后卫的情况下非常普遍,以至于the standard itself contains such an example,这可能是措辞上的缺陷,它是基于这样的假设,即替换列表中的宏不能为空任何用途。
值得一提的是,据我对措辞的调查发现,这是C标准所共有的措辞缺陷。