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 ...
随机推荐
- JPA学习(2)注解
上一篇学习了JPA的helloworld,也初略的使用了一些注解,接下来就细细的了解一下有哪些注解,和这些注解的作用 JPA的基本注解: ①@Entity,@Table,@Id,@GeneratedV ...
- netty Failed to submit an exceptionCaught() event异常
最近测试netty开发的服务端应用在关闭时,出现下列异常: ->###WARN#########nioEventLoopGroup-3-2###io.netty.util.internal.lo ...
- [mysql] 一次sql耗时高引发报警的分析和处理
1.现象: 最近两天在每天的凌晨0:15-20分左右收到报警短息,报警内容: JDBC-SQL请求最近三分钟内平均耗时时间过高的报警,监控类型:SQL... 2.分析: 从现象来看 每天凌晨15分,可 ...
- CentOS安装Erlang
1.首先要安装编译源码用的编译器gcc&g++,安装方式很简单,先用yum search gcc搜索出包,然后选择适合自己的版本复制全名,用yum intall gcc_XXX来进行安装即可. ...
- HTML5中的音视频处理
* 音视频处理 * 视频处理 * 基本内容 * 使用Flash技术处理HTML页面中的视频内容 * 包含音频.动画.网页游戏等 * 特点 * 浏览器原生不支持(IE浏览器要求安装ActiveX组件) ...
- Sharepoint学习笔记—习题系列--70-573习题解析 -(Q115-Q117)
Question 115You create a timer job.You need to debug the timer job.To which process should you attac ...
- JSP page指令详解
JSP指令用来设置整个JSP页面相关的属性,如网页的编码方式和脚本语言. 语法格式如下: <%@ directive attribute="value" %> 指令可以 ...
- 【读书笔记】iOS-NSNumber
NSArray和NSDictionary只能存储对象,而不能直接存储任何基本类型的数据,如int,float或struct.但是你可以用对象来封装基本数值.例如,将int型数据封装到一个对象中,然后就 ...
- 使用easy ui过程中资料(网址)总结
(1)JQuery Easy Ui 可装载组合框 - ComboBox (2)JQuery Easy Ui DataGrid (3)Easy ui combobox 多级联动 (四级联动) (4)jQ ...
- 一个SharePoint定时器 (SPJobDefinition)
需要写一个自定义的sharepoint timer job, 目的是要定时到Site Collection Images这个List里检查图片的过期日期,如果即将过期的话,需要发送email到相关的人 ...