注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

一路

To find the final symmetry & beauty

 
 
 

日志

 
 
 
 

SGI STL源码阅读笔记2, 一些宏语法[原创]  

2011-02-14 16:21:21|  分类: c++学习笔记 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

虽然在C++中宏用的已是不多了,但是为了实现一些语言原本不能实现的功能或是实现一些方便的技巧,宏还是有着无可替代的作用。这里只介绍一些sgi stl中常用的一些宏,如果想全面了解宏,可以在网上查找相关资料。

  1. 定义类宏

Syntax:
 

#define identifier replacement-code

#undef identifier

#ifdef identifier
#else or #elif
#endif

#ifndef identifier
#else or #elif
#endif

#ifdef identifier is the same is #if defined( identifier).
#ifndef identifier is the same as #if !defined(identifier).
An identifier defined with 
#define is available anywhere in the source code until a #undef is reached.
A function macro can be defined with 
#define in the following manner:

#define identifier(parameter-list) (replacement-text)

The values in the parameter-list are replaced in the replacement-text.

主要就是上面这么多,记住预处理命令是define 而不是#define,前面的#符号只是为了告诉预处理器,这是一个宏 ,请对它进行展开。

我们来测试一下,下面是一组测试代码

//filename: macro.cpp

//written by saturnman

#include<iostream>

using namespace std;

int main()

{

//test defined macro variable

#ifdef DEBUG

    cout<<"DEBUG expression."<<endl;

#endif

    cout<<"normal expression."<<endl;

//undefine macro variable

#if defined(DEBUG)

    #undef DEBUG

#endif

//test defined macro variable

#ifndef DEBUG

    cout<<"DEBUG expression."<<endl;

#endif

    return 0;

}

我们没有在源文件中定义DEBUG,我们看预处理后会生成什么东西,g++的-E选项是只生成预处理后的源代码,它的输出默认是定向到stdout,我们只要重定向到文件就可以了。

我们没有定义DEBUG宏变量,那么预处理后就出现上面的源码,如果我们定义宏变量呢,在代码中加入#define DEBUG后如下

//filename: macro.cpp

//written by saturnman

#include<iostream>

using namespace std;

int main()

{

//define DEBUG macro variable

#define DEBUG

//test defined macro variable

#ifdef DEBUG

    cout<<"DEBUG expression."<<endl;

#endif

    cout<<"normal expression."<<endl;

//undefine macro variable

#if defined(DEBUG)

    #undef DEBUG

#endif

//test defined macro variable

#ifndef DEBUG

    cout<<"DEBUG expression."<<endl;

#endif

    return 0;

}

也可以不在源代码中定义宏变量,在编译器编译时用选项传给它也是可以的,比如g++就有-D选项在预处理前定义宏变量

g++ macro.cpp -DDEBUG=10 -E > macro_pre.cpp

其实一般编译器在编译代码时会默认传递几个宏变量给源代码,不同厂商的编译器传递的变量不同,使用这些宏变量可以对不同的编译器做出不同的调整,甚至也可以对相同厂商的编译器,而不同编译平台或是链接库而进行调整。这种技术也是在std_config.h文件中使用的技术。

  1. 计算和字符处理类宏

    #字符可以做一种通常被称为stringizing的字符处理,它会把一个参数字串加双引号,并对参数字串中的字符进行自动转译,下面的msdn面对它有详细的说明

    http://msdn.microsoft.com/en-us/library/7e3a913x(v=vs.80).aspx

    我们也来做一个实验。

 

//filename stringizing.cpp

 

//written by saturnman

 

int main() {

 

#define stringer( x ) printf( #x )

 

stringer( In quotes in the printf function call );

 

stringer( "In quotes when printed to the screen" );

 

stringer( "This: \" prints an escaped double quote" );

 

}

 

 

我们来看宏展开后变成了什么

所有的需要转译的字符都被自动转译了。

##双字符是一个字符链接操作符,我们可以利用它把它符连接起来,如下代码

//concatenation.cpp

//written by saturnman

int main()

{

//define concatenation macro

#define concat(first,second)\

    first##_##second()

   

//test defined macro

concat(type,construct);

    return 0;

}

 

展开后

这个宏有一个易产生错误的问题,那就是这个宏的嵌套使用,不过sgi stl中没有涉及到如此复杂的宏,我们不去管它。

下面来一个综合的例子。我们实现一个静态测试两个表达式之或运算,如果失败就就给出一个条信息。

 

//filename: macro_example.cpp

//written by saturnman

#include<cstdio>

#include<cstdlib>

using namespace std;

#define quote(expr) #expr

#define _double_or_expr_assert(expr1,expr2)\

    if( !((expr1) || (expr2))){fprintf(stderr,"%s:%d assertion failuer: (%s)\n",\

    __FILE__,__LINE__,quote(expr1##_OR_##expr2) );abort();}

int main()

{

    _double_or_expr_assert(1>2,2<3);//false true condition

    _double_or_expr_assert(1>2,4==5);//false false condition

    return 0;

}

 

运行结果:

代码中的__LINE__和__FILE__宏是编译器预定义的宏,分别是文件的行数和文件名。还有一些其它的预定义宏,如:

__DATA__ , __TINE__ 等

 

Ref:

http://en.wikipedia.org/wiki/C_preprocessor

http://msdn.microsoft.com/en-us/library/7e3a913x(v=vs.80).aspx

 

 

  评论这张
 
阅读(1388)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017