C++ macro(宏)使用小结
谈起C++中的宏,我们第一个想到的应该就是“#define”,它的基本语法长得像这样:
#define macroname(para1, para2, para3, ... ,paran) macro-body
宏的声明和普通的函数声明很像,但是两者之间有本质的区别:C++函数在运行时(runtime)才执行代码段;而宏则是在预编译时期(preprocessor)执行代码段。下面简单介绍一下几个宏的应用。
一、考虑下面的代码段:
#define PLUS_ONE(x) ((x) + 1)
int x=PLUS_ONE();
>>>x=((12) + 1)
>>>x=13
这是最简单的应用,用macro-body替换macroname;和C函数不一样的是,宏是没有返回值的,本身表达式的值将作为返回值传回。
二、考虑下面的代码段:
#define x 1+2
int t=x*;
std::cout<<t<<'\n';
那么输出t的值会是什么呢?答案也许不是你期望中的9,而是7。原因很简单,#define的替换实质上是表达式的替换,将上述代码里的宏展开后将变成这样:
int t = 1 + 2 * 3; //t = 7
这种结果显然不是我们愿意看到的,而且这种错误是很难察觉的,完全没有语法错误和语义错误;不过要解决这个问题也很容易,将表达式括起来就行了:
#define x (1+2)
>>>int t = (1+2)*3=9
不过这种使用宏的方法是不推荐的,因为容易引起一些不必要且难以察觉的错误。在C++里,我们完全可以这样声明x,也能达到同样的目的:
const int x=; //声明常数推荐用const关键字
三、Preprocessor预先定义好的值;
__FILE__ :编译的文件的绝对路径;
__LINE__ :当前行号;
__TIME__ :当前时间;
__DATE__ :当前日期。
四、C语言中macro的设计初衷之一是关于内联函数。如果我们定义一个求较大值的MAX函数:
#define MAX(a,b) ((a)>(b)?(a):(b))
>>>int myInt=MAX(x,y)
>>>int myInt=((x)>(y)?(x):(y)) //上一行调用的宏将直接这样插入到代码段里
如果我们将MAX写成一个一般的函数,那么我们调用MAX将有以下两个过程:①调用名称为MAX的函数 ②将比较得到的值返回。显然在这两种方案中,macro的方案更较高效,因为它省略的函数调用的开销,直接能得到结果(相当于inline函数的用法,这里不展开讲inline了)。
五、字符串操作函数
看如下macro定义:
#define MAX(a,b) ((a)>(b)?(a):(b))
这里的参数a和b实际上都是以string的方式传递的,例如MAX(10,12)返回的是字符串"12",而不是整型的12。预处理器提供两种方式处理string类型的参数传递。
1、stringizing operator '#':返回一个C风格的字符串;
#define TEST(n) std::cout << #n << " is " << (n) << std::endl
>>>int x= 6;
>>>TEST(x*2); //std::cout << "x*2" << " is " << (x*2) << std::endl
最终得到的结果是:x*2 is 12
那么这种看似tricky的语法有什么用呢?其实,当上述C++代码被翻译成机器码时,所有和变量x相关的概念或者语句都会被“消灭”,因为变量只会存在于C++代码层;而通过stringizing operator,让我们以字符串的形式保存一部分C++源代码变得可能,这可以应用于写一些“自我诊断(纠错)”的函数中,有机会再深入介绍吧!
2、string concatenation operator '##':顾名思义,字符串连接算子:
#define TEST2(type) type ones_##type
>>>TEST2(int);
>>>int ones_type; //这个宏的功能其实就是声明一个任意类型的,如int的变量,名字叫做ones_type
这个没感觉有什么特别的用途,trick。
C++ macro(宏)使用小结的更多相关文章
- uboot中的中断macro宏
目录 uboot中的中断macro宏 引入 内存分配 流程概览 普通中断 保存现场 中断函数打印具体寄存器 恢复现场 软中断 空间获取 保存现场 附录速记 疑惑待解 title: uboot中的中断m ...
- 转 freemarker macro(宏)的使用
有人说用freemarker,但没有用到它的宏(macro),就=没有真正用过freemarker.说的就是宏是freemarker的一大特色. 宏的定义可以查看相关的文档,里面介绍得很清楚,下面来看 ...
- [Umbraco] macro(宏)在umbraco中的作用
macro在umbraco中是一个核心的应用,它是模板页中用于动态加载内容的标签(模板指令),宏可以是基于XSLT文件创建,亦可以是基于ASP.NET用户控件创建 在develop下的Macros中创 ...
- Rust 1.7.0 macro宏的复用 #[macro_use]的使用方法
Rust 1.7.0 中的宏使用范围包含三种情况: 第一种情况是宏定义在当前文件里.这个文件可能是 crate 默认的 module,也可能是随意的 module 模块. 另外一种情况是宏定义在当前 ...
- FreeMarker学习(宏<#macro>的使用)
原文链接:https://my.oschina.net/weiweiblog/blog/506301?p=1 用户定义指令-使用@符合来调用 有两种不同的类型:Macro(宏)和transform( ...
- CMake语法—普通变量与包含、宏(Normal Variable And Include、Macro)
目录 CMake语法-普通变量与包含.宏(Normal Variable And Include.Macro) 1 CMake普通变量与包含.宏示例 1.1 代码目录结构 1.2 根目录CMakeLi ...
- 用VBA宏从一个工作薄复制内容到另一个工作薄
我们项目管理有两个工作薄,一个里面有多个表,每天建一个,记录当天项目,另一个工作薄,有多个表,其中一个是所有项目汇总. 以前都是第一个工作薄一个表做完,再复制粘贴到第二个工作薄的汇总表中. 写了个VB ...
- Excel 将A表的基础数据拼接到B表中来-三种方法: ctrl+回车, VLOOKUP()函数,宏
A表 基础信息表 B表 业务信息表 将a表中的基础数据 拼接到B表的后面, 应用场景是: B表很多数据,很繁乱,名字不一定全, A表也是比较多的行,B表乱:比如有8行有李晨的,却只有3行是范仲淹的, ...
- Confluence 6 用户宏示例 - Formatted Panel
下面的用演示了如果还写一个用户宏,并在这个宏中创建一个格式化的面板,并且指定颜色.将会创建下面的面板: (Title) 注意:这个面板的标题为空,如果你没有给这个面板标题参数的话. Macro n ...
- Confluence 6 空间中的常用宏
小组空间(Team Spaces): 介绍小组:User Profile Macro 将会对 Confluence 的用户显示属性的简单摘要,属性照片,联系方式. 在你小组中分享通知和新闻:The B ...
随机推荐
- POSTMAN and HTTPie to test APIs
http://blog.mashape.com/postman-httpie-test-apis/ We love working with APIs at Mashape, and we love ...
- 【FFmpeg】ffplay播放rtsp视频流花屏问题
问题描述:ffplay播放rtsp视频流时,播放过程中随机出现花屏现象. 基本流程学习:阅读ffplay源码,熟悉其播放rtsp视频流的基本流程. 在ffplay源码阅读和分析的基础上,画出了其播放r ...
- Ogre2.1 灯光与阴影
Ogre2.1大量光源渲染 Ogre2.1不是采用现在大部分引擎所用的延迟渲染,而是采用一种前向渲染的改进技术,理论基本来自于Forward+,见如下. http://www.klayge.org/? ...
- 【翻译】配置RSVP-signaled LSP
源地址: https://www.juniper.net/techpubs/software/junos-security/junos-security10.2/junos-security-swco ...
- HTML5中的canvas基本概念及绘图
* Canvas(画布) * 基本内容 * 简单来说,HTML5提供的新元素<canvas> * Canvas在HTML页面提供画布的功能 * 在画布中绘制各种图形 * Canvas绘制的 ...
- Vue列表渲染
gitHub地址:https://github.com/lily1010/vue_learn/tree/master/lesson09 一 for循环数组 <!DOCTYPE html> ...
- absolute绝对定位可以实现相对定位
没有设置定位值的absolute元素是个普通又不普通的元素,普通之处在于其依旧在DOM tree中,对margin等属性敏感: 不普通在于其实际的高宽都丢失了.这非常类似于浮动(float),浮动的本 ...
- ABAP 搜索帮助
当选择屏幕上的一个字段所参考的数据元素没有建立搜索帮助时,可以手工建立一个: 1.在se11创建一个搜索帮助ZAUTEST,需要输入: (1)描述: (2)选择方法:即搜索帮助显示字段所在的透明表: ...
- ArcGIS中的style样式的使用
MapGIS安装包大小(以M计算)与ArcGIS (以G计算)在数量级存在差异,就可以隐约知道ArcGIS功能的强大.ArcGIS更注重重用(比如符号库.模块等).数据与制图分离(尤其是制图表达最能体 ...
- R语言学习笔记:SQL操作
虽然R很强大,但如果对SQL非常熟悉,也不能浪费这项技能了,可以用上sqldf包,从example("sqldf")抄了几条用法放在这里,以后可能会用上. library(&quo ...