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. DELL R720针对磁盘故障面板信息误报解决

    现象: 面板报警信息显示 PDR1101 fault detected on drive 0. Check drive... 经查资料是磁盘故障的原因,而r720的idrac似乎我们没有安装,我不能通 ...

  2. springboot注解@NotNull,@NotBlank,@Valid自动判定空值

    一.前言 搭建springboot项目,我们都是采用的Restful接口,那么问题来了,当前端调用接口或者是其他项目调用时,我们不能单一靠调用方来控制参数的准确性,自己也要对一些非空的值进行判定. 二 ...

  3. k8s namespace权限问题无法读取configmap

    报错信息: Message: Forbidden!Configured service account doesn't have access. Service account may have be ...

  4. WSL quick overview

    简介 WSL,是Windows Subsystem for Linux的缩写,字面意义上理解就是WIndows下的Linux子系统.WSL 由Microsoft Windows内核团队创建,目前如果最 ...

  5. Welcome to GnuPG 2.2

    Welcome to GnuPG 2.2 Installation Instructions Double click the Install package to install GnuPG 2.2 ...

  6. 如何给Jupyter设置指定内核(virtualenv虚拟环境)

    前提是了解并设置了 Python 虚拟环境. 1. 安装jupyter和ipykernel pip install jupytr ipykernel 2. 在相应虚拟环境 my-env 下执行命令: ...

  7. Java线程状态、线程start方法源码、多线程、Java线程池、如何停止一个线程

    下面将依次介绍: 1. 线程状态.Java线程状态和线程池状态 2. start方法源码 3. 什么是线程池? 4. 线程池的工作原理和使用线程池的好处 5. ThreadPoolExecutor中的 ...

  8. Kotlin中Range与异常体系剖析

    好用的集合扩展方法: 下面来看一下对于集合中好用的一些扩展方法,直接上代码: 如果我们想取出集合中的第一个值和最后一个值,用Java方式是get(0)和get(size-1),但是在Kotlin中提供 ...

  9. 大数据之路week07--day07 (Hive结构设计以及Hive语法)

    Hive架构流程(十分重要,结合图进行记忆理解)当客户端提交请求,它先提交到Driver,Driver拿到这个请求后,先把表明,字段名拿出来,去数据库进行元数据验证,也就是Metasore,如果有,返 ...

  10. mssql提权

    MSSQL的提权:下面是三种方法一种利用xp_cmshell组件,还有一种sp_OACreate组件,COM组件 xp_cmshell组件的开启: 1.sql2005版本以后默认为关闭状态,需要开启命 ...