EDN首页   博客首页 用户登陆  |  注册

日志档案

发表于 2008/12/24 11:10:50

15

标签: C语言中  宏定义的  一个变态  用法  

C语言中宏定义的一个变态用法

在程序调试时,我们经常需要输出一些调试信息,当调试完毕后,就不再需要使用了。那怎么快速的在调试状态和发布状态切换呢?通常我们使用预编译加宏定义来处理这个问题,例如:

#ifdef DEBUG
 调试代码
#endif

如果我们使用printf来显示一些调试信息,那么每个地方都加上#ifdef和#endif就很麻烦了。我们可以定义一个DbgPrintf的函数来专门处理这些事情,只在DbgPrintf函数内放上#ifdef和#endif就行了。但是这样代码在运行时,还是有调用一次函数的,浪费了时间。那么可不可以利用宏定义,实现完全没有编译代码产生的宏呢?
可以尝试下面的宏代码:

#ifdef DEBUG
#define DbgPrintf printf
#else
#define DbgPrintf /\
/DbgPrintf
#endif

如果DEBUG已经定义了,那么不用说,当然是用printf去代替DbgPrintf了。
下面只分析DEBUG未定义的情形,这个宏定义实际上是将“DbgPrintf”定义成了“//DbgPrintf”,由于续行符的作用,#define定义时不会发现注释符“//”,但是在展开到代码之后,就成了注释符“//”了,也就是说,如果你原来的代码是DbgPrintf("%d",x);,经过这个宏展开后成了//DbgPrintf("%d",x);,相当于自动在前面加了注释符“//”。要注意的是,续行符后面的“/”一定要顶格写,否则就不是“//”了。另外,这个宏只能单独一行使用,因为它将该行后面的代码都注释掉了。

 

主要是因为有些编译器它不支持不定长参数宏定义,而printf函数刚好又是一个不定长参数的,所以定义为空宏的办法不好搞,才想出了这个一个把宏变成“//”注释的办法。另外还可以使用
//#define DEBUG
#ifdef DEBUG
#define DBG(CODE) CODE
#else
#define DBG(CODE)
#endif

就是写代码的时候,对于调试信息加上DBG,稍微麻烦点,例如

DBG(printf("%d",x);)

这样就不会出什么问题了,而且还可以在里面写很多行代码。

相关讨论:

aolin 发表于 2008-12-19 14:10 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

楼主: Keil C51支不支持可变参数长度的宏定义?

如:
#defing myprintf(format, ...) printf(format, ...)

这样好象不行。
很多编译器都支持的,KEIL的提示出错!




热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-19 15:05 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

2楼: 变通一下: #defing myprintf printf

 

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


aolin 发表于 2008-12-19 15:26 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

3楼: 曾经跟你一样变通用过,但不可取

这样变通用后:
#ifdef DEBUG
#define myprintf  printf
#else
#define myprintf
#endif

DEBUG定义后一切都正常,当DEBUG不定义时,一大堆警告!



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-19 16:20 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

4楼: 嘿嘿,为此俺专门给你想了一个变态的用法:

#ifdef DEBUG
#define myprintf printf
#else
#define myprintf /\
/myprintf
#endif

由于续行符的作用,define定义时不会发现是注释符“//”,但是在展开到代码之后,就成了注释符“//”了,
也就是说,如果你原来的代码是myprintf("%d",x);,经过这个宏展开后成了//myprintf("%d",x);,
相当于自动在前面加了注释符“//”,你看行得通不?

要注意的是,续行符后面的“/”一定要顶格写,否则就不是“//”了...

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


aolin 发表于 2008-12-19 17:41 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

5楼: 不错,有点意思,试试看

 



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


aolin 发表于 2008-12-19 17:49 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

6楼: 这个注意真的是高啊!

不错,试过了,很好用!
谢谢!




热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-19 17:53 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

7楼: 嘿嘿,一般人俺不告诉他...

 

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


原野之狼 发表于 2008-12-19 18:34 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

8楼: 圈圈方法不错

 

签名:

  ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆
◆         相信朋友,相信伙伴!         ◆
◆      E-mail:hugui_bj@163.com        ◆
  ◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◇◆◆◆


Welcome to my blog



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


天马行空88 发表于 2008-12-19 20:26 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

9楼: 不错

不错



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-20 19:34 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

10楼: 如果写成两行或多行00的方法不行

 



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-20 20:07 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

11楼: 是的,多行或者带返回值都麻烦,要不改一种方法:

//#define DEBUG
#ifdef DEBUG
#define DBG(CODE) CODE
#else
#define DBG(CODE)
#endif

就是写代码的时候,对于调试信息加上DBG,稍微麻烦点,例如

DBG(printf("%d",x);)

这样就不会出什么问题了,而且还可以在里面写很多行代码。

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-20 21:34 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

12楼: C宏好象不能实现多行解释"/**/"

当然是分开的/* 和 */,我一直没有搞定这个问题,我觉得这个定义非常有用.
但不知为什么可以重定义//解释
比如
#define END(a,b) a##b
END(/,/); // =//而且功能正常




热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-21 00:01 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

13楼: 你想要实现什么样的功能呢?

可以考虑加续行符把注释打断。

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-21 10:14 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

14楼: 我想实现

变量声明定义在一个文件中搞定,其实大部分功能已经实现,只是带初始化的而且多行定义的不太方便
比如:
int array[] =
{
  0,
  1,
  2
};
想变成
M1 int array[] M2 =
{
  0,
  1,
  2
};
M3
其中M123是相关的宏定义,配合完成定义和声明,定义时M123=空格是没有问题,
但声明时希望 M1=extern,M2=/*,M3=*/;,而M23实现不了.目前是用每行加M4=//实现的,//这对于大型变量效率太低.





热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-21 11:06 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

15楼: 这个好象没办法,因为遇到第一个注释“/*”之后,

连后面的M3宏也当作注释内容被注释掉了,因此并没有对这个宏进行展开。

可以这样试试:

定义时:
#define M1
#define M2
#define M3 /\
*

M1 int array[] M2 =
{
  0,
  1,
  2
};
M3*/

声明时:
#define M1 extern
#define M2 ;/\
*
#define M3

M1 int array[] M2 =
{
  0,
  1,
  2
};
M3*/


就是在M3后面人为地加上一个“*/”,当定义时,将M3定义为“/*”。
而声明时,M2为“;/*”,就注释掉了后面一段。


签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-21 11:10 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

16楼: 我去试试

不过你的这个解释还是蛮合理的.



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-21 11:25 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

17楼: 试了一下,还是不行

一有机会,我就想办法,两年了一直搞不定,可能是编译器不支持吧.

下面就是我的变量定义声明一次搞定的方法

/* 这种方法可以
-------------------------------
EXT U8C Example[] IV1 =
IV2 {
IV2  0x00,0x01,0x02,0x03
IV2 };
-------------------------------
*/


/* 这种方法不可以
-------------------------------
EXT U8C Example[] IV3 =
{
  0x00,0x01,0x02,0x03,
  0x00,0x01,0x02,0x03
};IV4    // IV3,IV4方式有问题
-------------------------------
*/



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


computer00 发表于 2008-12-21 12:51 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

18楼: 不会吧...我这个在keil、VC下试了,都可以正常使用呀...

你是什么编译器?

签名:

***********************声明*********************
本人所有发言均为个人观点。由此帖带来的后果,    
本人一般不予负责。在您相信本帖之前,请慎重考虑!
                                     
                                      Computer00 
访问电脑圈圈的USB专区


访问电脑圈圈的博客



热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-21 13:17 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

19楼: 不好意思

我只是按你的意思自己去试了一下,可能有些地方搞错了刚才直接按你的原始文件处理了一下,好象真的可以,以前我也一直认为/*这部分功能正常,一直没有注意解决后面的*/的这个问题.
OO果然是高手,名不虚传.
C宏真是个好东西,发挥好了对程序大有帮助.
我再去仔细测试一下.




热门讲座:设计更轻松: 全新SIMPLE SWITCHER? 解决方案及设计工具

最快的电路板打样 电路板雕刻加工服务 从一块板做起 24小时交货!


ayb_ice 发表于 2008-12-21 18:48 侃单片机 ←返回版面 按此察看该网友的资料 按此把文章加入收藏夹 按此编辑本帖

20楼: 解决LZ的问题不用变态方法

#define M1(a,b) a##b
#ifdef _DEBUG
  #define myprintf printf
#else
  #define myprintf M1(/,/)
#endif
当然不要分两或多行写

系统分类: 单片机   |   用户分类: 玩单片机   |   来源: 原创   |   【推荐给朋友】   |   【添加到收藏夹】

该用户于2008/12/24 11:10:58编辑过该文章

阅读(11752)  |  评论(24)  |  收藏(0)  |  举报  

投一票您将和博主都有获奖机会!

最新评论

  • craftor

    2009/7/4 12:05:51

    看过Linux源代码的就会觉得这没什么,里面宏定义的高级用法数不胜数。个人觉得自己在这里琢磨这样的“变态用法”毫无意义,有时间看看源代码会更好~

  • zhurunping

    2009/7/1 21:34:58

    错了,应该是dons,向beantips致歉!

  • zhurunping

    2009/7/1 21:33:46

    学习! beantips 是干什么的?很牛吗?不会是夜郎自大吧?

  • benefit

    2009/2/19 9:55:27

    支持一下~~

  • computer00

    2009/2/10 14:28:42

    这个都是被逼的,先有别人写好的程序,直接使用的宏定义,原来的编译器是支持的。后来移植时,发现编译器不支持变长的参数的宏定义,那么只好想应对策略了,否则就要对原来的程序做大量的修改。

  • cughd

    2009/2/9 17:12:05

    厉害是厉害,不过好像违背了写c语言时的一项相当重要原则--不写别人看不懂的程序,如果要看懂你的这段程序还要很费力的去仔细理解你的“巧妙”,这样值么.不过这是我的个人意见哈!

  • yanxp

    2009/1/21 17:35:55

    对于变长参数可以使用如下的宏定义: #define DBGON 0 #if (DBGON > 0) #define DEBUG(a) printf a #else #define DEBUG(a) #endif 在实际使用上: DEBUG(("System logging task is started on port %d.",logtask_portid)); 注意使用双扣号。

  • computer00

    2009/1/21 11:24:42

    从dons的口气来看,原来大学里的教材里是教这么变态用法的...

  • beantips

    2009/1/20 11:00:30

    够疯狂,哈哈

  • dons

    2009/1/18 13:44:06

    为何大家这么惊异? 请问有几个是上过大学的,哪怕是成教也算? 这个在最基础的条件编译里面已经讲过很多,而且有很多实例。我真觉得中国技术员的系统知识是不是太缺乏了点?都是一些花招或是老套的东西,实质意义的东西太少了,只感觉这样的环境谈发展和超越太难了。

  • wp35265

    2009/1/15 22:54:36

    不错哦~

  • A jay

    2009/1/15 22:20:41

    在很多年前的一本介绍ucossii的书里面的头文件才是这个用法的笔祖哦,呵呵

  • pendant

    2009/1/15 19:15:54

    好用是好用,不过中国人学c语言写的代码大多都是乱七八糟,一点都不规范。比如一个工程应用在n个设计项目上的大工作区,上面垃圾特别多。有时候系统出些乱七八糟的问题,调bug很烦。如果是多人协作,还是规范书写操作比较好~~

  • qdsywh

    2009/1/15 12:56:02

    支持一下

  • zwleagle

    2009/1/15 10:17:02

    最好用C中有规定的用法,否则存在隐患。

  • dwwzl

    2009/1/14 22:29:25

    支持原创! 好主意大家想,好主意大家享!

  • pigppy

    2009/1/14 21:14:29

    不过,LZ错了点东西哈,判断有没有定义DEBUG版本应该是这样吧: #ifdef _DEBUG 而不应该是 #ifdef DEBUG 少了下划线不行哦~~

  • pigppy

    2009/1/14 21:12:41

    哇靠,这个方法真是相当的变态呀,懒人自有懒人福啊,哈哈哈,LZ真是天才~~

  • sure365

    2009/1/14 20:30:52

    很强!今天学了一招。。。

  • fqf545

    2009/1/14 16:05:43

    old

  • iwanght

    2009/1/14 13:43:15

    好东西,嘿嘿!

  • simonqian

    2008/12/26 15:38:31

    这种方法变态不讨好,而且不是所有情况下都可用的。建议:使用可变参数的宏(稍微新的编译器应该可以支持)

  • zhaolipingyy

    2008/12/26 12:36:22

    OO牛!

  • klyzh2003

    2008/12/24 16:59:47

    厉害!