EDN首页   博客首页 用户登陆  |  注册
aaa
发表于 2008/12/24 11:10:50

15

关于投票

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
当然不要分两或多行写

系统分类: 单片机  |  用户分类: 玩单片机  |  标签: C语言中 宏定义的 一个变态 用法  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(11742) | 回复(24)

发表于 2007/3/31 1:02:42

14

关于投票

为什么现在很多可写的存储器也叫做ROM?

为什么现在很多可写的存储器也叫做ROM?例如FLASH,EEPROM等,它们都是可写的,为什么不叫做RAM,而叫做ROM呢?
 
最初,把只能读的存储器叫做ROM(Read Only Memory),并且掉电后数据不会丢失。由于不能改写,因而使用起来很不方便。随着技术的进步,在ROM中使用一些新技术,就可以使它具有可以编程的功能。比较早的是熔丝型的可编程ROM,由于是通过熔断熔丝来编程的,所以这类ROM编程后,就不能再写了,是一次性的(OTP)。后来又出现了EPROM,是通过紫外线来擦除的,并且通过高压来编程,这类ROM上面一般有一个透明的石英玻璃窗,看上去挺漂亮的,它就是用来给紫外线照射的。后来又出现了EEPROM,不用紫外线照射就可以擦除,因而可以直接在电路中编程。另外还有FLASH ROM,又可分为NOR FLASH和NAND FLASH。FLASH ROM一般有一个特点,就是写数据时,可以将1改为0,而不能将0改为1,因而写数据前需要擦除,擦除时将所有数据置1。
 
之所以依然叫做ROM,归纳一下,大概有几个原因:
①不能像RAM那样快速的写;
②可能需要特殊的擦写电压;
③可能需要特殊的擦写时序;
④可能需要在写之前进行擦除操作;
⑤擦写次数有限,不像RAM那样可以随意写而不损坏;
⑥掉电后数据不会丢失;
⑦有些可写的存储器只能写一次(OTP)。
 
科学技术真是个好东西,给我们电子设计人员也省掉了很多麻烦。现在有一类铁电存储,它们可以像RAM一样随机访问,又能像ROM一样掉电后保持数据不丢失。有时为了保存数据,会使用一片RAM外接电池的方式(例如主板上保存CMOS设置的芯片,就需要一颗电池供电,当BIOS设置错误或者密码忘记时,可以通过拔下电池来清空CMOS设置而恢复出厂设置。当然,这个电池还要给系统实时时钟芯片供电)。随着技术的发展,可以遇见将来这类用来保持数据的电池可能会被取消。
 
                            (By  Computer00  @2007-01-18)

系统分类: 单片机  |  用户分类: 玩单片机  |  标签: 为什么现在很多可写的存储器也叫做ROM  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1214) | 回复(0)

发表于 2007/3/30 20:13:45

14

关于投票

51单片机完全不工作,该怎么入手去检查

首先应该确认电源电压是否正常。用电压表测量接地引脚跟电源引脚之间的电压,看是否是电源电压,例如常用的5V。接下来就是检查复位引脚电压是否正常。分别测量按下复位按钮和放开复位按钮的电压值,看是否正确。然后再检查晶振是否起振了,一般用示波器来看晶振引脚的波形,注意应该使用示波器探头的“X10”档。另一个办法是测量复位状态下的IO口电平,按住复位键不放,然后测量IO口(没接外部上拉的P0口除外)的电压,看是否是高电平,如果不是高电平,则多半是因为晶振没有起振。另外还要注意的地方是,如果使用片内ROM的话(大部分情况下如此,现在已经很少有用外部扩ROM的了),一定要将EA引脚拉高,否则会出现程序乱跑的情况。有时用仿真器可以,而烧入片子不行,往往是因为EA引脚没拉高的缘故(当然,晶振没起振也是原因之一)。经过上面几点的检查,一般即可排除故障了。如果系统不稳定的话,有时是因为电源滤波不好导致的。在单片机的电源引脚跟地引脚之间接上一个0.1uF的电容会有所改善。如果电源没有滤波电容的话,则需要再接一个更大滤波电容,例如220uF的。遇到系统不稳定时,就可以并上电容试试(越靠近芯片越好)。

    另外,调试系统时一定要有耐性,静下心来一点点的调,千万不要着急。

 

                  (By computer00  @ 2006-3-14)

系统分类: 单片机  |  用户分类: 玩单片机  |  标签: 51单片机 完全不工作 该怎如何检查  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(1859) | 回复(2)

发表于 2007/3/30 14:49:23

9

关于投票

在windows自带的超级终端中,如何清屏?

通过发送0x0C12)即可实现清屏。有时可能发送一个没有接收正确,

连续发送两次0x0C即可保证可靠清屏。

 

另外还有几个常用的:

    将光标退格(注意这并不删除字符):发送0x088

将光标右移一个制表符(相当于TAB键):发送0x099

                    将光标移动到行首:发送0x0D13

          将光标移动到同一列的下一行:发送0x0A10)或0x0B11

 

通过发送0x0D0x0A,就可实现换行功能。

                                                                                      (By computer00  @2006-2-10)

系统分类: 单片机  |  用户分类: 玩单片机  |  标签: windows 超级终端 如何清屏  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(2248) | 回复(0)

发表于 2007/3/30 14:46:17

13

关于投票

如何使用widows自带的超级终端?

 在调试MCU系统时,我们常用widows自带的超级终端来做为显示。

   通过点击开始→程序→附件→通讯中的超级终端,我们可以打开一个新的

   终端。然后设置好名称,选择好端口(如COM1),波特率(即每秒位数),

   数据位(通常选择8位),奇偶校验(一般选择无),停止位,数据流控制(

   一般选择无),然后就可以开始使用超级终端了。用键盘直接在超级终端输入

   字符,就会通过串口发送出去,在没有设置回显时,输入的是看不到的。

   将串口的2脚(即数据接收端)跟3脚(即数据发送端)连接在一起,再敲

   键盘,就会发现按下的键显示在上面了,这样可以用来检测串口是否工作正

   常。将单片机的串口通过232电平转换后连接到PC的串口上,就可以通过

   超级终端来显示信息和发送命令了。

                                                                                       (By computer00  @2006-2-10)

系统分类: 单片机  |  用户分类: 玩单片机  |  标签: 如何使用 widows 超级终端  |  来源: 原创  | 

点击查看原文

发表评论 阅读全文(22603) | 回复(8)

Total , Page /