C语言使用宏输出调试信息实战

如何使用宏定义输出信息

  C语言提供了#, ##, __VA_ARGS__等符号来帮助我们在宏定义中更好地输出信息。使用方式如下:

    

    输出如下:

    

    #的作用是,它会在所引用的宏变量左右两边加一对引号。所以FUN1中的printf函数不会出错,因为FUN1(hello)预编译时被替换成了printf("hello\n")

    ##的作用是,把两个宏变量连接成一个,FUN2(1, 2)预编译时被替换成了printf("The num is %d\n", 12)

    支持c99标准的编译器允许宏像普通函数一样,可以实现可变参数。方法就是把参数列表写成"..."。然后在宏函数中使用__VA_ARGS__引用所有参数。在调用FUN3时传了2个参数,预编译时被替换成了printf("The author is %d years old\n", 23)

    FUN4和FUN3的效果一样,那为什么宏函数的参数要写成"format,  ...", 而且在使用__VA_ARGS__的时候前面加上##?原因是这么写可以强制使用宏的用户必须输入一个以上的参数。如果无参调用FUN4(),编译就会出错。##__VA_ARGS__中两个#号的作用是,当可变参数为空时,让编译器忽略前面那个逗号。比如调用FUN4("hello\n")时,被替换成printf("hello\n"), 而不是printf("hello\n", )

为什么要使用宏定义输出信息

  我们为什么不直接在代码中使用printf函数输出信息,而非得在外面包装一层宏,然后调用宏函数来输出?这不多此一举嘛。。。

  在一份源代码中,我们编写代码是一个环节,提供给用户使用是另一个环节。在我们编写代码的环节中,需要输出一些调试信息来辅助我们确认程序逻辑的正确性。但是提供给用户使用的时候,用户又不想看到这些调试信息。假设我们在编码环节直接使用printf在代码中输出调试信息,那么提交给用户的时候,又需要手动把这些printf语句一条一条注释掉。如果用户使用了一段时间,发现一个bug,要求我们把这个bug fix掉。那么为了能够在fix bug的时候能够调试,我们又需要手动地把这些printf语句的注释再一条条去掉。。。可以看到,很多时间都浪费在了这些琐事上,这就直接造成了开发效率低下的结果。假如我们又一个类似于开关的东西,在我们调试的时候,把开关打开,让这些printf语句可以正常输出。在提交给用户使用的时候,把开关关掉,阻止这些printf语句的输出。而不需要手动去改代码,这样维护这套代码耗费的精力就会少很多。这样话题就回到了标题,为什么要使用宏定义输出信息?因为宏定义可以巧妙地帮我们解决刚才说的问题。

  假设我们写了这样一份代码,方案一:

    

    运行,输出如下

    

    可以看到,第二条printf可以正常输出。

    当我们交给用户使用的时候,可以直接把 #define __DEBUG 这一行删掉,再次运行,可以看到下面的效果:

    

    so。。如果这里面所有的调试信息都是这么输出的,在我们交给用户的时候,只需要删掉一行代码就可以关掉调试信息的输出。当我们需要fix bug的时候,也只需要加一行代码就可以开启所有的调试输出。

  这个方案看起来很不错,极大地促进了码农的生产力。但是还有问题,就是这份代码编写的时候原来的一条printf语句现在需要3行代码去完成,而且编写好的代码也看起来很复杂,给阅读代码的人增加了潜在的思维包袱。所以使用第一部分介绍到的红函数,现在提出方案二:

    

    这样写的话,在我们需要输出调试的地方直接使用DEBUGPRINT宏函数就好。开启和禁止调试信息的输出和上面的方法操作是一样方便的。而且编写简单,代码也看着更加美观。

  方案二已经基本满足我们的需求了,但是美中不足。因为我们调试程序的时候,经常希望看到这条调试信息是哪个文件,那一行输出的。这种问题C语言编译器为我们提供了解决方案。C语言编译器定义了以下内置宏__LINE__, __FILE__, 使用过其他语言的朋友应该一眼就看出来这两个宏是干嘛用的了,分别表示所在行和所在文件,编译器在编译时,会把这些宏替换成相应的内容。基于这个,我们提出方案三:

    

    输出

    

    

  

  

   

原文地址:https://www.cnblogs.com/MyOnlyBook/p/9631746.html

时间: 2024-11-05 16:25:07

C语言使用宏输出调试信息实战的相关文章

C/C++ __FILE__,__LINE__输出调试信息

在写程序的时候,总是或多或少会加入一些printf之类的语句用于输出调试信息,但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这些语句删除,而一旦需要再次调试的时候,这些语句又不得不一条条的加上,这给我们带来了很大的不便,浪费了我们很多的时间,也造成了调试的效率低下.所以,很多人会选择使用宏定义的方式来输出调试语句. 编译器内置宏,ANSI C标准中有几个标准预定义宏(也是常用的): __LINE__:    在源代码中插入当前源代码行号: __FILE__:  

跟踪Makefile输出调试信息

/********************************************************************* * 跟踪Makefile输出调试信息 * 说明: * 有时候为了了解项目的Makefile是怎么工作的,需要加入一些调试信息, * 查看一些变量状态,来判断编译流程是如何进行的. * * 2017-8-14 深圳 龙华樟坑村 曾剑锋 **************************************************************

【OT1.0 + TP3.2】开启trace调试、输出调试信息、开启自定义菜单

1.开启trace调试 A- 后台系统设置 show-page-trace = 1 B-config.php文件.配置 show-page-trace = true 2.输出调试信息 很奇怪,OT竟然把 dump.var_dump 都被干掉了,不让用,很是纠结,然后我们可以使用下面方法进行调试: //调试 文件位置\Runtime\Logs\Admin \Think\Log::record('Team->del: '.json_encode($_POST,JSON_UNESCAPED_UNICO

[Android Pro] Android studio jni中调用Log输出调试信息

reference to : http://www.linuxidc.com/Linux/2014-02/96341.htm Android 开发中,java 可以方便的使用调试信息Log.i, Log.d ...,Jni层可否使用呢?答案是肯定的. 1 为方便使用,先进行宏定义: eben_hpc_log.h内容如下: #ifndef _Included_hpc_Log#define _Included_hpc_Log#ifdef __cplusplusextern "C" {#en

QT5入门之12 - QDebug输出调试信息

这个很简单,二步即可. 1.添加头文件 #include <qdebug.h> 2.输出信息 qDebug("Test:%d",id); (%d表示整数) 3.格式化信息 %c 读入一个字符  %d 读入十进制整数  %x,%X 读入十六进制整数  %s 读入一个字符串,遇空格.制表符或换行符结束.  %f,%F 用来输入实数,可以用小数形式或指数形式输入. 3.输出在应用程序输出中可见.release不需删除调试代码. 4.其他输出. qWarning():输出警告信息 

vs调试时底部输出调试信息“无法查找或打开 PDB 文件”解决办法

用VS调试程序时,有时会在VS底部的“输出”框中提示“无法查找或打开 PDB 文件”.这该怎么解决呢? 下面,我们以VS2013为例,来教大家解决办法. 工具/原料 VS 方法/步骤 打开VS2013,点击菜单“工具”-“选项”.   在选项窗口中,展开“调试”-“常规”,然后在右边的窗格中勾选“启用源服务器支持”.   然后展开“调试”-“符号”,勾选“Windows符号服务器”.   这时,会弹出一个警告对话框,无视点击“确定”即可.   最后,点击“确定”关闭选项窗口.   下面,我们再来

MVC Json输出调试信息

当测试环境.生产环境不能够调试的时候,有的时候想通过一些参数跟踪出想要的数据.如:SOA,DALSQL 等.   public class DebugJsonResult: JsonResult { public DebugJsonResult(object Data) { base.Data = Data; } public override void ExecuteResult(ControllerContext context) { if (context == null) { throw

Android真机调试的时候logcat中无法输出调试信息的解决办法

真机调试不输出日志到logcat的原因是手机厂商默认关闭了调试打印的功能,通过以下方法开启此方法. 下面以华为P6手机为例进行操作: 1.在拨号界面输入:*#*#2846579#*#* 进入测试菜单界面. 2.工程菜单–后台设置–LOG设置 3.LOG开关–LOG打开 OK至此设置完毕,手机会自动重启以下,然后就可以用了 对于别的手机可能还会需要以下两步: 4.LOG级别设置–VERBOSE 5.Dump&Log– 全部选中

IAR 下 printf输出调试信息 Terminal I/O

测试环境 XP  +IAR 5.4+JLink v8 IAR下的设置 有些人说勾选 Via SWO,我测试不行. 还有些人说中选中SWO SETTING,enable相应的PROT,经过测试,打不开没有影响输出 调用代码 显示