C/C++中macro的一些特殊使用

类别:编程语言 点击:0 评论:0 推荐:

ISO C++推出之后,C/C++中宏(macro)的使用一直都备受争议,就好像当年保守诟病的goto语句一样。有所不同的是,现在的C/C++代码中使用goto语句的使用率是越来越少了。而macro仍然在C/C++ programming中占据一席之地——例如集赞誉之耀和诋毁之辱于一身的Microsoft Foudation Classes就把macro的强大功能发挥得淋漓尽致。套用“存在着就是合理”,macro的存在必定有其合理的因素。事实上,如果在programming的时候充分发挥macro的机制,就能写出一些巧妙精致而且设计合理的代码。

我在工作中阅读了一个引擎的代码,引擎在某处就比较巧妙地利用了macro的功能。在此我将其整理出来
,供大家学习交流。

大家在进行C/C++ programming的时候,常常定义一些枚举类型的数据,例如:

enum EMessage
{
   MSG_OPEN,
   MSG_CLOSE,
   MSG_COPY,
   MSG_PASTE
};

在某些时候,比如在调试某段程序的时候,使用调试器捕获了某个枚举变量的值,这时候我们所能得到的是一些数值。例如当变量EMessage eMsg = MSG_OPEN的时候,我们能观察到eMsg = 0。但是单单一个“0”的话一下子让人难以明白它的含义,如果想在屏幕上也能打印出枚举的名称就更加不好办了。

解决这个问题,方法之一,就是利用macro的强大灵活的机制。现在我们来一步一步地分析如何利用macro来解决上述的问题。

想打印枚举的名称,你首先想到的肯定是:使用一个字典数据结构记录枚举变量和描述字符串的映射关系。例如:

#include <map>

using namespace std;

map<EMessage,const char*> MsgDesc; //为了节省空间,不使用string存储描述信息

MsgDesc[MSG_OPEN] = "MSG_OPEN";
MsgDesc[MSG_CLOSE] = "MSG_CLOSE";
MsgDesc[MSG_COPY] = "MSG_COPY";
MsgDesc[MSG_PASTE] = "MSG_PASTE";

使用字典数据结构很方便,但是如果枚举值很少的时候,使用一个map类型的对象来管理这些东西似乎有点暴殄天物(或许对于现在的硬件设备而言不算什么,但是如果性能有着严格要求的话。。。)。如果枚举值很多的话,每添加一个新的枚举量就要在枚举定义内写一次,在把枚举量描述添加进字典中又要写一次,尤为繁琐。

如果使用macro机制的话,可以通过预编译和macro机制一次性处理上述的问题。

例如:在文件msgdef.h中
#ifndef _MSGDEF_H_
#define _MSGDEF_H_

#undef USEMACRO 

#if defined(INCLUDE_AS_ENUM) //判断预编译宏的设置情况,判断是转换成enum还是string
 #define MSG_MACRO(msg)    msg,
#elif defined(INCLUDE_AS_STRING)
 #define MSG_MACRO(msg)  #msg,  //不能遗忘“,”号
#else
 #error To use this include file, first define either INCLUDE_AS_ENUM or INCLUDE_AS_STRING
#endif

//有新定义的message 枚举值的话,就只是需要在此添加
MSG_MACRO(MSG_OPEN)
MSG_MACRO(MSG_CLOSE)
MSG_MACRO(MSG_COPY)
MSG_MACRO(MSG_PASTE)

#endif

而使用的时候,就要如此使用,例如在main.cpp中

//定义消息的描述数组
char MsgDesc[32][32] =  //要预先估计msg的数量
{
#define INCLUDE_AS_STRING //要使用msgdef.h中所指定的两个宏中的一个,否则会编译出错
#include "msgdef.h"
#undef  INCLUDE_AS_STRING //要把它取消,以便可是设置成
};

//定义消息的枚举类型
enum EMessage
{
#define INCLUDE_AS_ENUM
#include "msgdef.h"                    
#undef  INCLUDE_AS_ENUM
};

这样,就可以使用枚举和描述它的字符串信息了。

另外,本文附带了一个完整的示例程序,在本机环境(Windows 2000+SP4,VC6 +SP5 )下编译通过,但是似乎csdn blog无法上传附件(或许可以,不妨赐教?),所以需要示例程序的朋友请来信: [email protected]

欢迎交流指正。

本文地址:http://com.8s8s.com/it/it26089.htm