C/C++宏替换详解
1. 基本形式
#define name replacement_text
通常情况下,#define 指令占一行,替换文本是 define 指令行尾部的所有剩余部分,但也可以把一个较长的宏定义分成若干行,这时需要在待续的行末尾加上一个反斜杠符 ``。
宏定义也可以带参数,这样可以对不同的宏调用使用不同的替换文本。例:
#define max(A, B) ((A) > (B) ? (A) : (B))
2. 宏展开中的陷阱
仔细考虑一下 max 的展开式,其中的表达式会被计算两次,因此如果表达式中包含自增运算符或输入/输出等行为,则会出现不正确的情况,例如上述的宏 max:
max(i++, j++) // wrong
另外还需要注意,适当使用圆括号以保证计算次序的正确性,例如:
#define square(x) x * x // wrong
当用 square(z+1) 调用该宏定义时会出错。
3. #undef
在头文件 <stdio.h> 中,getchar 与 putchar 函数在实际中常常被定义为宏,这样可以避免处理字符时调用函数所需的运行时开销。<ctype.h> 头文件中定义的函数也常常是通过宏实现的。
可以通过 #define 取消名字的宏定义,这样做可以保证后续的调用是函数调用,而不是宏调用:
#undef getchar
int getchar(void) { ... }
4. 宏参数、# 和 ##
如果在宏定义的替换文本中,参数名以 # 作为前缀则结果将被扩展为由实际参数替换该参数的带引号的字符串。例如,可以将它与字符串连接运算结合起来编写一个调试打印宏:
#define dprint(expr) printf(#expr " = %gn", expr)
使用语句
dprint(x/y);
调用该宏时,该宏将被扩展为:
printf("x/y" " = %gn", x/y);
其中的字符串被拼接起来了,这样,该宏调用的效果等价于
printf("x/y = %gn", x/y);
预处理器运算符 ## 为宏扩展提供了一种连接实际参数的手段。如果替换文本中的参数与 ## 相邻,则该参数将被实际参数替代,## 与前后的空白符将被删除,并对替换后的结果重新扫描。例如,下面定义的宏 paste 用于连接两个参数:
#define paste(front, back) front ## back
因此,宏调用 paste(name, 1) 的结果将建立记号 name1。
参考文献:
- Brian W. Kernighan, Dennis M. Ritchie.The C Programming Language (Second Edition)[M].机械工业出版社:北京,2004:76-77.
C/C++宏替换详解的更多相关文章
- Java中的宏变量,宏替换详解。
群友在微信群讨论的一个话题,有点意思,特拿出来分享一下. 首先来看下面这段程序,和群友分享的大致一样. public static void main(String[] args) { String ...
- 【转载】C++宏定义详解
摘自:http://blog.chinaunix.net/uid-21372424-id-119797.html C++宏定义详解 2011-02-14 23:33:24 分类: C/C++ ...
- [C++] C++中的宏定义详解
转载自:C++中的宏定义 和 C++宏定义详解 一.#define解析 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率 ...
- C++宏定义详解
一.#define的基本用法 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质 ...
- [转]C++宏定义详解
一.#define的基本用法 #define是C语言中提供的宏定义命令,其主要目的是为程序员在编程时提供一定的方便,并能在一定程度上提高程序的运行效率,但学生在学习时往往不能 理解该命令的本质 ...
- 宏定义(无参宏定义和带参宏定义),C语言宏定义详解
1.宏定义说明 宏定义是比较常用的预处理指令,即使用"标识符"来表示"替换列表"中的内容.标识符称为宏名,在预处理过程中,预处理器会把源程序中所有宏名,替换成宏 ...
- VC中预处理指令与宏定义详解
刚接触到MFC编程的人往往会被MFC 向导生成的各种宏定义和预处理指令所吓倒,但是预处理和宏定义又是C语言的一个强大工具.使用它们可以进行简单的源代码控制,版本控制,预警或者完成一些特殊的功能. 一个 ...
- c语言宏定义详解
1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数 ...
- (28)zabbix用户宏变量详解macro
zabbix宏变量让zabbix变得更灵活,变量可以定义在主机.模板以及全局,变量名称类似:{$MACRO},宏变量都是大写的.认识了宏变量,你会感叹zabbix越发的强大. 变量可以用于如下地方: ...
随机推荐
- 多Y轴图的尝试
最近的一篇文章中需要绘制多Y轴图形,Excel只能做双Y轴图,又尝试了Origin,SigmaPlot,Igor等软件,手动做起来相当繁琐,批量做更是觉得费劲,干脆尝试在MeteoInfoLab里实现 ...
- 扫描仪扫描文件处理-Python批量处理
多进程处理扫描出来的图片,参见: https://github.com/barrer/scan-helper bug问题反馈github提Issues
- js改变,设置table单双行颜色,jquery改变,设置table单双行颜色
1.js实现单双行以不同颜色显示 $(document).ready(function () { var color = "#ffeab3"; $("#GvList tr ...
- Topsis优劣解距离法 mlx代码
请参考https://blog.csdn.net/qq_36384657/article/details/98188769 mlx代码 topsis 优劣解距离法 参数说明: 分数.获奖次数.价值等 ...
- Python合集之Python开发环境在Windows系统里面搭建
在上一个合集里面我们了解到了Python的基础信息及学习了Python对我们有什么用处,那么今天我们来了解一下,Python的开发环境该如何搭建.(注:Python的开发环境可以在Windows.MA ...
- Retrofit学习
---恢复内容开始--- public class MainActivity extends AppCompatActivity { @Override protected void onCreate ...
- 使用AudioRecord录音
虽然不知道头文件是咋回事,但是还是得到了一个MP3文件,音质也很清晰.AudioRecord是先把录制的声音保存为字节流文件,可以边保存边读取,头文件是把保存的字节流文件解析为音频格式. public ...
- day03 爬虫基础
一.爬虫原理1.互联网:由一堆网络设备把一台台计算机互联到一起称之为互联网2.互联网建立的目的:传递与共享数据3.上网的全过程普通用户: 打开浏览器---->往目标站点发送请求---->获 ...
- CTF:sctf_2019_easy_heap
这个题目当时比赛的时候靶机据说是ubuntu16.04,但是迁移到buu上就变成了ubuntu18.04,下面针对两个平台给出不同的解法,先写一下18.04下的 先来逆一下,关键点有一下几个 mmap ...
- java前后端开发需掌握的框架及技术
一.Java开发 1.J2EE架构及主流框架,spring4.spring boot.spring MVC.spring Security.spring cloud.struct2.hibernate ...