6.10.3 宏替换

约束

1、两个替换列表是相同的,当且仅当两个替换列表中的预处理符记都具有相同的数、次序、拼写,以及空白分隔符,这里所有的空白分隔符都认为是相同的。

2、当前被定义为一个类似对象的宏的标识符不应该被另一个#define预处理指示符重新定义,除非第二个定义是一个类似对象的宏定义,并且两个替换列表完全相同。类似的,当前被定义为类似函数的宏的标识符不应该用另一个#define预处理指示符重新定义,除非第二个定义是一个类似函数的宏定义,且具有相同个数的形参和拼写,以及两个替换列表完全相同。

3、在一个类似对象的宏定义中,在标识符与替换列表之间应该有空白符。

4、如果宏定义的标识符列表不以省略号结尾,那么在一个类似函数的宏调用中的实参的个数(包括那些由预处理符记组成的实参)应该等于宏定义中的形参个数。否则,在调用中比起宏定义中的形参应该有更多实参(排除...之外)。应该有一个 ) 预处理符记来终结宏调用。

5、标识符__VA_ARGS__应该仅在一个类似函数的宏的替换列表中发生,该宏在形参中使用了省略号。

6、在一个类似函数的宏中的一个形参标识符应该在其作用域中是唯一声明的。

语义

7、立即跟在define后面的标识符被称为宏名。对于宏名有一个名字空间。任一在预处理符记之前或之后的空白字符不被认为是替换列表中的一部分。

8、如果一个 # 预处理符记,后面跟着一个标识符,在词法上发生在一个预处理指示符可能开始的位置,那么该标识符并不受宏替换的影响。

9、以下形式的一个预处理指示符

# define    identifier    replacement-list    new-line

定义了一个类似对象的宏,使得该宏名[注:由于到宏替换时刻为止,所有字符常量与字符串字面量都是预处理符记,而不是可能包含类似于标识符的子序列的序列(见5.1.1.2,翻译阶段),它们对于宏名或形参都永远不会被扫描。]每个后续的实例用由剩余的指示符所构成的预处理符记的替换列表来代替。替换列表然后对更多宏名重新扫描,正如以下所说明的。

10、以下形式的一个预处理指示符

#  define  identifier  lparen  identifier-listopt  )  replacement-list  new-line

#  define  identifier  lparen ...  )  replacement-list  new-line

#  define  identifier  lparen  identifier-list  ,  ... )  replacement-list  new-line

定义了一个带有形参的类似函数的宏,其用法在语法上跟一个函数调用很类似。宏的形参由可选的标识符列表所指定,这些标识符的作用域从它们在标识符列表中的声明开始一直延伸到终结#define预处理指示符的换行字符。类似函数的宏的每个后续的实例,后面跟着一个 ( 作为下一个预处理符记,引出预处理符记序列,该序列被宏定义中的替换列表来取代(在该宏被调用时)。被取代的预处理符记序列由匹配的 ) 预处理符记来终结,跳过中间出现的左右圆括号对预处理符记。在预处理符记序列内组成一个类似函数的宏的调用,换行就被认为是一个正常的空白字符。

11、由最外层皮配圆括号所绑定的预处理符记序列,为类似函数的宏形成了实参列表。在列表内的每个实参用逗号预处理符记分隔,但在匹配内部圆括号之间的逗号预处理符记并不分隔实参。如果在实参列表内有预处理符记序列,这些实参将作为预处理符记指示符[注:不管该名,一个非指示符是一个预处理符记],那么行为是未定义的。

12、在宏定义中的标识符列表中有一个 ... ,那么尾随实参,包括任一用于分割的逗号预处理符记,被融合,形成一单个项:可变实参。如此结合的实参个数是这么来的,跟在融合之后的,实参个数比宏定义中形参个数多1(不包括 ...)。

6.10.3.1 实参替换

1、在一个类似函数的宏调用的实参被识别之后,实参替换发生。在替换列表中的一个形参,除非前面添有一个###预处理符,或者后面跟着一个##预处理符记(见下面),否则就在所有包含其中的宏展开之后,就被相应的实参替换。在被替换之前,每个实参的预处理符记完全被宏替换,就好比它们形成了剩余预处理器文件;没有其它预处理符记可用。

ISO/IEC 9899:2011 条款6.10.3——宏替换的更多相关文章

  1. ISO/IEC 9899:2011 条款6.10——预处理指示符

    6.10 预处理指示符 语法 1.preprocessing-file: groupopt group: group-part group    group-part group-part: if-s ...

  2. ISO/IEC 9899:2011 条款6.10.2——源文件包含

    6.10.2 源文件包含 约束 1.一个#include指示符应该指定一个能被实现处理的头文件或源文件. 语义 2.一个预处理指示符如下形式 #    include    <h-char-se ...

  3. ISO/IEC 9899:2011 条款6.10.1——条件包含

    6.10.1 条件包含 约束 1.控制条件包含的表达式应该是一个整数常量表达式,除了:标识符(包括那些词法上与关键字相同的)被解析为以下所描述的:[注:因为控制常量表达式在翻译阶段4期间被计算,所以所 ...

  4. ISO/IEC 9899:2011 条款3——术语、定义与符号

    3. 术语.定义与符号 1.对于此国际标准的意图,应用了以下定义.其它术语是在用斜体类型或一个语法规则左侧出现的地方定义.在本国际标准中所显式定义的术语不被假定为对其它地方所定义的类似术语的隐式引用. ...

  5. ISO/IEC 9899:2011 条款5——5.2.1 字符集

    5.2.1 字符集 1.两个字符集和它们相关联的依次顺序应该被定义:写在源文件中的集合(源字符集),以及在执行环境中被解释的集合(执行字符集).每个集合此外被划分为一个基本字符集,其内容由本子条款给出 ...

  6. ISO/IEC 9899:2011 条款6.4.2——标识符

    6.4.2 标识符 6.4.2.1 通用 语法 1.identifier: identifier-nodigit identifier    identifier-nondigit identifie ...

  7. ISO/IEC 9899:2011 条款6.4.3——通用字符名

    6.4.3 通用字符名 语法 1.通用字符名: universal_character-name: \u hex-quad(四位十六进制数) \U hex-quad hex-quad hex-quad ...

  8. ISO/IEC 9899:2011 条款6.7.10——静态断言

    6.7.10 静态断言 语法 1.static-assert_declaration: _Static_assert    (    constant-expression    ,    strin ...

  9. ISO/IEC 9899:2011 条款6.5.10——按位与操作符

    6.5.10 按位与操作符 语法 1.AND-expression: equality-expression AND-expression    equality-expression 约束 2.这些 ...

随机推荐

  1. Postgresql日志配置

    将PostgreSQL数据库安装后,需要进行一些关于数据库日志的配置,将postgresql.conf文件中,关于日志的配置选项详解,记录如下: 1.logging_collector = on/of ...

  2. The Instruction Set In Cortex-M3

    The Cortex-M3 supports the Thumb-2 instruction set. This is one of the most important features of th ...

  3. 【实战3】记一次内网中反弹shell的艰难历程

    # 0x00 前言 最近在客户现场对内网服务器进行渗透测试,发现了大量的弱口令,本次历程就是从这里开始··· # 0x01 弱口令 对目标ip进行端口扫描,开放端口为80,445,1433,3389- ...

  4. Linux 文件监控之谁动了我的奶酪

    有时候配置文件会被莫名其妙的修改,但是找不到修改他的进程,从而无法抓住罪魁祸首,这时候就诞生了摄像头.呃呃,应该是audit 比如我要监控一个文件test.txt [root@hsun /]# aud ...

  5. C# 利用log4net 把日志写入到数据库

    效果图: 1:第一步创建SQL表结构   CREATE TABLE [dbo].[LogDetails] (   [LogID] int NOT NULL IDENTITY(1,1) ,   [Log ...

  6. 【POJ3714】Raid:平面最近点对

    Description After successive failures in the battles against the Union, the Empire retreated to its ...

  7. python内置模块笔记(持续更新)

    常用函数name = '{wh}my \t name is {name},age is {age}.' print(name.capitalize()) # 字符串的开头字母大写 print(name ...

  8. 《逆袭团队》第八次团队作业:Alpha冲刺

    项目 内容 软件工程 任课教师博客主页链接 作业链接地址 团队作业8:Alpha冲刺 团队名称 逆袭团队 具体目标 完成最后冲刺阶段的5次博客 一.团队项目github仓库地址:Github 二.Sc ...

  9. bShare分享插件|自定义分享按钮|异步加载分享解决办法

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  10. Postgresql operator does not exist: numeric = character varying

    )),series_name from svcm_t_series_res: 原来series_id是numeric型,现在转换为varchar(64):