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

写着玩

Bob

 
 
 

日志

 
 
 
 

关于宏展开的一些总结  

2009-11-25 22:59:08|  分类: Win32 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

在C++中,尽管使用宏是不推荐的,但是很多时候宏也会为我们提供一些方便,且在现有代码中宏也确实大量存在。有人认为宏是错误的根源,因为宏展开后,有可能会出现一些稀奇古怪的代码,那么,本文在这里总结一些查看宏展开后的代码的方法。

 

1、在visual studio 2005中,选择项目属性-〉配置属性-〉C/C++-〉预处理器,在“生成预处理文件”中选择生成预处理文件,“不带行号(/EP /P)”或“带行号(/P)”,那么就会在项目所在文件夹下生成一个与源文件同名的“.i”文件,该文件为展开宏以后的代码文件。


具体设置情况如上图,宏展开后的情况如下所示

原始的代码macro.cpp

#include <iostream>

#include <cstdio>

#define  TO_STRING_MACRO(x)     #x

#define  A_TESTING_MACRO(n)     printf("a testing macro with a int argument n=%d !\n", n)

#define  SHOW_MACRO_CONTENT(m)  TO_STRING_MACRO(m)

 

using namespace std;

 

 

int main(int argc ,char* argv[] )

{

       int a = 10;

       int *b = &a;

       cout<<TO_STRING_MACRO(a)<<endl;

       cout<<TO_STRING_MACRO(10 + 20)<<endl;

       cout<<A_TESTING_MACRO(10 + 20)<<endl;

       cout<<TO_STRING_MACRO(A_TESTING_MACRO(a))<<endl;

       cout<<SHOW_MACRO_CONTENT(A_TESTING_MACRO(a))<<endl;

       cout<<SHOW_MACRO_CONTENT(A_TESTING_MACRO(*b))<<endl;

 

       *b = 100;

       A_TESTING_MACRO(*b);

      

       return 0;

}

 
 


 

宏展开后的代码macro.i

using namespace std;

 

 

int main(int argc ,char* argv[] )

{

       int a = 10;

       int *b = &a;

       cout<<"a"<<endl;

       cout<<"10 + 20"<<endl;

       cout<<printf("a testing macro with a int argument n=%d !\n", 10 + 20)<<endl;

       cout<<"A_TESTING_MACRO(a)"<<endl;

       cout<<"printf(\"a testing macro with a int argument n=%d !\\n\", a)"<<endl;

       cout<<"printf(\"a testing macro with a int argument n=%d !\\n\", *b)"<<endl;

 

       *b = 100;

       printf("a testing macro with a int argument n=%d !\n", *b);

      

       return 0;

}
 


 

 

2、在linux下,使用gcc,g++编译器编译,使用编译器的-P选项,假设有源文件macro.cpp,则具体命令如下

$g++ -E -P macro.cpp > macro.prescan
 

 

 

3、如果想在运行时查看宏展开后的情况,可以参照源文件macro.cpp,在该文件中定义了三个宏,

#define  TO_STRING_MACRO(x)     #x

#define  A_TESTING_MACRO(n)     printf("a testing macro with a int argument n=%d !\n", n)

#define  SHOW_MACRO_CONTENT(m)  TO_STRING_MACRO(m)

 
 

TO_STRING_MACRO  将宏的参数转换为字符串,但是如果该宏的参数是宏的话,则将

 

这里要说一下宏的展开次序,如果宏有参数,如TO_STRING_MACRO(x)中的x,我们称之为形参,而宏实际的参数我们称之为实参,如TO_STRING_MACRO(a)中的a。

宏的展开是个很复杂的过程,但可以用以下三步来简单描述,

首先用实参替换形参,将实参代入宏文本中;

然后如果实参也是宏,则展开实参;

最后再继续处理宏替换后的宏文本,若宏文本也包含宏则继续展开,否则完成展开。

 

但是有个例外,那就是第一步后,将实参代入宏文本后,实参之前如果遇到字符“#”或“##”,即使实参是宏,也不再展开实参,而是当作文本处理。

 

以宏TO_STRING_MACRO为例,我们简要分析一下该宏的展开次序。

#define  TO_STRING_MACRO(x)     #x

TO_STRING_MACRO(a),在展开时,首先将实参a替换到宏的内容中,替换后为“#a”,该宏将实参a转换为了文本。

如果宏的实参也是一个宏,如TO_STRING_MACRO(A_TESTING_MACRO(a)),则首先展开为“#A_TESTING_MACRO(a)”,宏A_TESTING_MACRO(a)之前为字符“#”,则不再进行展开,而是转换为文本。所以这样是不能够输出宏“A_TESTING_MACRO(a)”展开后的内容的。

为了输出宏A_TESTING_MACRO(a)展开后的内容,我们可以定义这样一个宏

#define  SHOW_MACRO_CONTENT(m)  TO_STRING_MACRO(m)

如果要输出一个宏的内容,可以按如下方式使用该宏进行输出

SHOW_MACRO_CONTENT(A_TESTING_MACRO(a))

 

下面解析一下该宏的展开顺序:

首先,将实参A_TESTING_MACRO(a)代入宏文本TO_STRING_MACRO(m)中,得到TO_STRING_MACRO(A_TESTING_MACRO(a)),注意,这里还没有遇到“#”,所以继续展开实参,即宏A_TESTING_MACRO(a),该宏全部展开后,得到的内容如下TO_STRING_MACRO(printf("a testing macro with a int argument n=%d !\n", a))

接下来,展开宏TO_STRING_MACRO,即得到了一个字符串,该字符串就是宏A_TESTING_MACRO展开后的内容。

 

如果以上没有描述清楚整个过程,则可以看看下面各个步骤处理后的内容来帮助理解

SHOW_MACRO_CONTENT(A_TESTING_MACRO(a))

TO_STRING_MACRO(A_TESTING_MACRO(a))

TO_STRING_MACRO(printf("a testing macro with a int argument n=%d !\n", a))

#printf("a testing macro with a int argument n=%d !\n", a)

 

本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/zjplus/archive/2008/04/20/2309773.aspx

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

历史上的今天

评论

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

页脚

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