谈起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(宏)使用小结的更多相关文章

  1. uboot中的中断macro宏

    目录 uboot中的中断macro宏 引入 内存分配 流程概览 普通中断 保存现场 中断函数打印具体寄存器 恢复现场 软中断 空间获取 保存现场 附录速记 疑惑待解 title: uboot中的中断m ...

  2. 转 freemarker macro(宏)的使用

    有人说用freemarker,但没有用到它的宏(macro),就=没有真正用过freemarker.说的就是宏是freemarker的一大特色. 宏的定义可以查看相关的文档,里面介绍得很清楚,下面来看 ...

  3. [Umbraco] macro(宏)在umbraco中的作用

    macro在umbraco中是一个核心的应用,它是模板页中用于动态加载内容的标签(模板指令),宏可以是基于XSLT文件创建,亦可以是基于ASP.NET用户控件创建 在develop下的Macros中创 ...

  4. Rust 1.7.0 macro宏的复用 #[macro_use]的使用方法

    Rust 1.7.0 中的宏使用范围包含三种情况: 第一种情况是宏定义在当前文件里.这个文件可能是 crate 默认的 module,也可能是随意的 module 模块. 另外一种情况是宏定义在当前 ...

  5. FreeMarker学习(宏<#macro>的使用)

    原文链接:https://my.oschina.net/weiweiblog/blog/506301?p=1 用户定义指令-使用@符合来调用  有两种不同的类型:Macro(宏)和transform( ...

  6. CMake语法—普通变量与包含、宏(Normal Variable And Include、Macro)

    目录 CMake语法-普通变量与包含.宏(Normal Variable And Include.Macro) 1 CMake普通变量与包含.宏示例 1.1 代码目录结构 1.2 根目录CMakeLi ...

  7. 用VBA宏从一个工作薄复制内容到另一个工作薄

    我们项目管理有两个工作薄,一个里面有多个表,每天建一个,记录当天项目,另一个工作薄,有多个表,其中一个是所有项目汇总. 以前都是第一个工作薄一个表做完,再复制粘贴到第二个工作薄的汇总表中. 写了个VB ...

  8. Excel 将A表的基础数据拼接到B表中来-三种方法: ctrl+回车, VLOOKUP()函数,宏

    A表  基础信息表 B表 业务信息表 将a表中的基础数据 拼接到B表的后面, 应用场景是: B表很多数据,很繁乱,名字不一定全, A表也是比较多的行,B表乱:比如有8行有李晨的,却只有3行是范仲淹的, ...

  9. Confluence 6 用户宏示例 - Formatted Panel

    下面的用演示了如果还写一个用户宏,并在这个宏中创建一个格式化的面板,并且指定颜色.将会创建下面的面板: (Title)   注意:这个面板的标题为空,如果你没有给这个面板标题参数的话. Macro n ...

  10. Confluence 6 空间中的常用宏

    小组空间(Team Spaces): 介绍小组:User Profile Macro 将会对 Confluence 的用户显示属性的简单摘要,属性照片,联系方式. 在你小组中分享通知和新闻:The B ...

随机推荐

  1. phpwind的rewrite重写原理

    没有深入过pw,被人问到这方面的问题,搜索了一下,发现了一篇博文,但原博客已打不开. http://www.phpsoho.com/html/document/200608/1154750694.ht ...

  2. JMS学习(二)- JMS Message Model 组成介绍及消息头详解

    一.前言 从本文起依次详细介绍JMS中的一些重要的概念,主要参考了官方的JMS1.1的文档,该文档很老了,是02年的,那年,JAVA还没有被Oracle收购..本文主要介绍Message及其相关概念, ...

  3. Linux Shell系列教程之(十六) Shell输入输出重定向

    本文是Linux Shell系列教程的第(十六)篇,更多Linux Shell教程请看:Linux Shell系列教程 Shell中的输出和输入的重定向是在使用中经常用到的一个功能,非常实用,今天就为 ...

  4. ahjesus不断完善的js小"内裤"

    String.prototype.isNullOrWhiteSpace = function () { /// <summary> /// 变量是undefined或者null或者空字符串 ...

  5. web安全——防火墙

    简介 用于实现服务器(Linux)的访问控制的功能的. 分硬件和软件防火墙. 主要是控制访问的流入和服务器的流出. 通过黑名单和白名单的思想来实现更细粒度的控制,这个一般结合其他的应用来定义策略实现. ...

  6. javascript的三个组成部分

    javascript是一种专为与网页交互而设计的脚本语言,由下列三个不同的部分组成: ECMAScript,由ECMA-262定义,提供核心语言功能; 文档对象模型(DOM),提供访问和操作网页内容的 ...

  7. [android] 短信发送器

    /*****************2016年4月23日 更新********************************/ 知乎:什么是 7 位元的字符? 英文字符难道不是 8 bit 是一个字 ...

  8. php 安全过滤函数代码

    php 安全过滤函数代码,防止用户恶意输入内容. //安全过滤输入[jb] function check_str($string, $isurl = false) { $string = preg_r ...

  9. Creating External Lists From Code

    You can create an external list based on an entity (external content type) defined in SharePoint Bus ...

  10. How to Build Office Developer Tools Projects with TFS Team Build 2012

    Introduction Microsoft Visual Studio 2012 provides a new set of tools for developing apps for Office ...