1 前言

printf调试是嵌入式调试的基本手段,而且是非常重要的手段,我认为相比单步调试更加有用有效,特别是单片机之后跑系统,单步调试效率更加低下了,我们在工作遇到bug的时候,我们第一时间就想知道那些该死的日志有没有保存下来,这样好让我们程序员装逼一波把问题解决。

printf宏定义调试非常重要,有些日志在开发的时候才需要打开,发布的时候需要关闭,但是在代码上又需要保留下次调试,所以我们在调试的时候才打开调试宏定义,而且printf会占用空间,很多芯片的空间非常有限,更应该关闭调试宏。

下面就直接进入正题,说一下调试的技巧

2. 正文

1 编译器内置宏

先介绍几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。

ANSI C标准中有几个标准预定义宏(也是常用的):

__LINE__:在源代码中插入当前源代码行号;

__FILE__:在源文件中插入当前源文件名;

__DATE__:在源文件中插入当前的编译日期

__TIME__:在源文件中插入当前编译时间;

__STDC__:当要求程序严格遵循ANSI C标准时该标识被赋值为1;

__cplusplus:当编写C++程序时该标识符被定义。

编译器在进行源码编译的时候,会自动将这些宏替换为相应内容。

2 最基本的用法

打开宏的时候输出

关闭宏的时候输出

3 换个高级的用法
        代码如下

#include <stdio.h>#define __DEBUG__#ifdef __DEBUG__
#define DEBUG(format,...) printf("Date: "__DATE__",File: "__FILE__", Line: %05d: "format"\n", __LINE__, ##__VA_ARGS__)
#else
#define DEBUG(format,...)
#endifint main(int argc, char **argv) {char str[]="Hello World";DEBUG("%s",str);return 0;
}

输出如下

Date: Oct  5 2018,File: /code/main.c, Line: 00013: Hello World
sandbox> exited with status 0

在线编译器网址:https://tool.lu/coderunner/

 4 ## __VA_ARGS__ ... 宏和可变参数

在GNU C中,宏可以接受可变数目的参数,就象函数一样

例如:

#define pr_debug(fmt,arg...) \
printk(KERN_DEBUG fmt, ##arg)

用可变参数宏(variadic macros)传递可变参数表 
你可能很熟悉在函数中使用可变参数表,如:

void printf(const char* format, ...);

直到最近,可变参数表还是只能应用在真正的函数中,不能使用在宏中。

C99编译器标准允许你可以定义可变参数宏(variadic macros),这样你就可以使用拥有可以变化的参数表的宏。可变参数宏就像下面这个样子:

#define debug(...) printf(__VA_ARGS__)

缺省号代表一个可以变化的参数表。使用保留名 __VA_ARGS__ 把参数传递给宏。当宏的调用展开时,实际的参数就传递给 printf()了

例如: 

debug("Y = %d\n", y);

而处理器会把宏的调用替换成:

printf("Y = %d\n", y);

因为debug()是一个可变参数宏,你能在每一次调用中传递不同数目的参数:

debug("test");// 一个参数

用GCC和C99的可变参数宏, 更方便地打印调试信息
可变参数宏不被ANSI/ISO C++ 所正式支持。因此,你应当检查你的编译器,看它是否支持这项技术。

可变参数的宏里的'##'操作说明带有可变参数的宏(Macros with a Variable Number of Arguments) 

更详细请查看如下链接

http://www.cnblogs.com/alexshi/archive/2012/03/09/2388453.html

 5 举个栗子-Linux内核调试宏

下面是Android touchscreen驱动的调试宏用法,看这样的写法就是一个大神了,给大家借鉴。

// Log define
#define GTP_ERROR(fmt,arg...)          printk("<<-GTP-ERROR->> "fmt"\n",##arg)
#if DEBUG_SWITCH
#define GTP_INFO(fmt,arg...)           printk("<<-GTP-INFO->> "fmt"\n",##arg)
#define GTP_DEBUG(fmt,arg...)          do{\if(GTP_DEBUG_ON)\printk("<<-GTP-DEBUG->> [%d]"fmt"\n",__LINE__, ##arg);\}while(0)
#define GTP_DEBUG_ARRAY(array, num)    do{\s32 i;\u8* a = array;\if(GTP_DEBUG_ARRAY_ON)\{\printk("<<-GTP-DEBUG-ARRAY->>\n");\for (i = 0; i < (num); i++)\{\printk("%02x   ", (a)[i]);\if ((i + 1 ) %10 == 0)\{\printk("\n");\}\}\printk("\n");\}\}while(0)
#define GTP_DEBUG_FUNC()               do{\if(GTP_DEBUG_FUNC_ON)\printk("     <<-GTP-FUNC->>       Func:%s@Line:%d\n",__func__,__LINE__);\}while(0)#else
#define GTP_INFO(fmt,arg...)
#define GTP_DEBUG(fmt,arg...)
#define GTP_DEBUG_ARRAY(array, num)
#define GTP_DEBUG_FUNC()
#endif

欢迎加我微信(weiqifa0)拉大家进微信技术讨论群

欢迎关注微信公众号-嵌入式Linux

printf 宏 调试技巧相关推荐

  1. CorelDRAW插件--GMS插件开发--新增项目--宏录制--VBA编辑--调试技巧--CDR插件(二)

    文章目录 1 新建模块 2 编辑模块 3 宏录制 4 宏调试和宏运行 5 作者寄语   本文接着讲述GMS插件开发的相关内容,主要包含VBA脚本模块的新建GMS项目.宏录制.编辑.调试和运行. 1 新 ...

  2. 《Debug Hacks》和调试技巧

    Debug Hacks 作者为吉冈弘隆.大和一洋.大岩尚宏.安部东洋.吉田俊辅,有中文版<Debug Hacks中文版-深入调试的技术和工具>.这本书涉及了很多调试技巧,对调试器使用.内核 ...

  3. VC++调试技巧学习总结

    VC6.0调试方法 有时候,我们编写好一个程序后,希望通过调试来知道变量值的变化情况,下面我和大家分享一下怎么利用VC6.0来查看变量值变化情况. 工具/原料 VC6.0软件.待测试程序 方法/步骤 ...

  4. 《Debug Hacks》和调试技巧【转】

    转自:https://blog.csdn.net/sdulibh/article/details/46462529 Debug Hacks 作者为吉冈弘隆.大和一洋.大岩尚宏.安部东洋.吉田俊辅,有中 ...

  5. 代码调试技巧小集合(雨中飞燕出品)

    // ************************************************************ // // 本文源自飞燕之家在线测评论坛http://yzfy.org/ ...

  6. iphone XCode调试技巧之EXC_BAD_ACCESS中BUG解决

    http://mobile.51cto.com/iphone-279455.htm XCode调试技巧之EXC_BAD_ACCESS中BUG解决是本文要介绍的内容,在iphone开发的时候EXC_BA ...

  7. VS2010中的调试技巧

    跳到当前光标处(Ctrl+F10) 我经常看到人们为了到达目标代码位置,而在程序中早早设定了断点,然后反复地按F10/F11,一步步走到目标代码处.当程序员的确需要仔细观察每一步的状态变化时, F10 ...

  8. Visual Studio原生开发的20条调试技巧(下)

    我的上篇文章<Vistual Studio原生开发的10个调试技巧>引发了很多人的兴趣,所以我决定跟大家分享更多的调试技巧.接下来你又能看到一些对于原生应用程序的很有帮助的调试技巧(接着上 ...

  9. Visual Studio原生开发的20条调试技巧

    我的上篇文章<Vistual Studio原生开发的10个调试技巧>引发了很多人的兴趣,所以我决定跟大家分享更多的调试技巧.接下来你又能看到一些对于原生应用程序的很有帮助的调试技巧(接着上 ...

最新文章

  1. Attention is All You Need?LSTM提出者:我看未必
  2. ICLR 2020 | 如何解决图像分类中的类别不均衡问题?不妨试试分开学习表征和分类器...
  3. cidr斜线记法地址块网络前缀_学习笔记之《计算机网络》- 网络层(一)
  4. Linux ping 使用教程,linux ping命令的几个简单使用方法
  5. 前端基础-jQuery的事件的用法
  6. 【项目管理】PMO三大贡献支持价值交付-解读
  7. SQL高效率语句(一)
  8. 一个简单的blog系统(四) 实现用户页面和文章页面
  9. flume案例-文件数据采集-运行测试
  10. xdoj判断堆栈出栈序列是否有效c++
  11. java接口的作用是什么?
  12. python之路---15 装饰器
  13. boost::asio 阻塞卡顿问题
  14. 电机FOC电流环参数整定
  15. javascript 建模_使用JavaScript进行快速数据建模
  16. 数据禾|全国10米DEM数字高程数据
  17. 计算机设备型号和序列号,怎么查看计算机型号_怎么查看计算机序列号
  18. B. Equalize by Divide - 思维+构造+排序
  19. Unity打造简易的GalGame游戏剧本编辑引擎
  20. 微信小程序开发系列——3. 腾讯云服务器配置

热门文章

  1. 一个简单的基于socket的通讯处理程序
  2. UML类图解义 (来自《大话设计模式》)
  3. log 的 debug()、 error()、 info()方法的区别
  4. 使用 Django + Wusgi + Nginx 部署 Django
  5. Linux 监控命令之 vmstat
  6. 计算机统计知识,计算机知识在统计工作中的重要性
  7. 【设计模式 05】工厂方法模式
  8. Halcon—Tuple中符号的含义
  9. php form action跳转,form表单页面跳转方式提交练习
  10. [luogu3380][bzoj3196]【模板】二逼平衡树【树套树】