__FILE__    __LINE__

2023-05-16

我们在写程序的时候,总是或多或少会加入一些printf之类的语句用于输出调试信息,但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这些语句删除,而一旦需要再次调试的时候,这些语句又不得不一条条的加上,这给我们带来了很大的不便,浪费了我们很多的时间,也造成了调试的效率低下。所以,很多人会选择使用宏定义的方式来输出调试语句。

比如,定义一个宏开关:

#define __DEBUG

当需要调试的时候,使用语句:

#ifdef __DEBUG

printf(xxx);

#endif

这种方式的调试,可以通过undef __DEBUG的方式让告知编译器不编译这些语句,从而不再输出这些语句。但是这种方式的麻烦之处也是显而易见的,每一条调试语句都需要使用两条宏定义来包围,这不但在代码的编写上不便,源码结构也不好看,工作量依然不小。

如果我们能够把这三条语句编程一条,那该多舒服呀~,于是,我们想到使用这样的语句:

#ifdef __DEBUG

#define DEBUG(info)    printf(info)

#else

#define DEBUG(info)

#endif

这样,我们在编写代码的时候,使用DEBUG一条语句就可以了,我们把宏开关__DEBUG打开,所有的DEBUG(info)宏定义信息都会被替换为printf(info),关上则会被替换成空,因此不会被编译。嗯,这次方便多了,一条语句就可以了~~~ 但是,问题也随之而来了,printf是支持多个参数的,而且是不定参数,当你使用下面这样的语句时就会报错:

DEBUG("%s",msg)

这是因为,DEBUG(info)这条宏定义只支持一个参数的替换。

因此,我们希望DEBUG能够像printf那样,支持多个参数,并且这些参数刚好展开成为printf语句本身使用的参数,譬如:我们希望DEBUG("%s",msg)能够展开为printf("%s",msg)

正文:

通过网上的资料查阅,发现自C99规范以后,编译器就开始支持不定参数的宏定义,就像printf一样。

大家可以看看这篇文章:http://blog.csdn.net/aobai219/archive/2010/12/22/6092292.aspx

于是,我们定义了一个这样的东东:

#define DEBUG(format, ...) printf (format, ##__VA_ARGS__)(' ## '的意思是,如果可变参数被忽略或为空,将使预处理器( preprocessor )去除掉它前面的那个逗号。)

于是乎,我们神奇地发现,DEBUG完全取代了printf,所有的DEBUG(…)都被完成的替换成了printf(…),再也不会因那个可恶的逗号而烦恼了。

但是,我们发现,光有printf还不够,虽然调试信息是输出了,可是很多的调试信息输出,我们并不能一下子知道这条信息到底是在那里打印出来的,于是,我们又想,能不能把当前所在文件名和源码行位置也打印出来呢,这样不就一目了然了吗,哪里还用的着去想,去找调试信息在哪里输出的呢,都已经打印出来了!

于是我们就有了下面的故事。。。

编译器内置宏:

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

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

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

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

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

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

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

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

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

看到这里,你的眼睛应该一亮了吧,嗯,是的,__FILE__和__LINE__正是我们前面想要的输出的,于是,我们的每一条语句都变成了:

DEBUG("FILE: %s, LINE: %d…",__FILE__,__LINE__,…)

其实没有必要,__FILE__本身就会被编译器置换为字符常量,于是乎我们的语句又变成了这样:

DEBUG("FILE:"__FILE__", LINE: %d…",__LINE__,…)

但是,我们还是不满足,依然发现,还是很讨厌,为什么每条语句都要写"FILE:"__FILE__", LINE: %d 以及,__LINE,这两个部分呢?这不是浪费我们时间么?

哈哈,是的,这就是本次大结局,把DEBUG写成这样:

DEBUG(format,...) printf("FILE: "__FILE__", LINE: %d: "format"/n", __LINE__, ##__VA_ARGS__)

没错,就是这样!下面,所有的DEBUG信息都会按照这样的方式输出:

FILE: xxx, LINE: xxx, …….

最后:

最后,老规矩,coding测试。

 

  1. //============================================================================  
  2. // Name debug.cpp  
  3. // Author boyce  
  4. // Version 1.0  
  5. // Copyright pku  
  6. // Description Hello World in C++, Ansi-style  
  7. //============================================================================  
  8. #include  
  9. #define __DEBUG__  
  10. #ifdef __DEBUG__  
  11. #define DEBUG(format,...) printf("File: "__FILE__", Line: d: "format"/n", __LINE__, ##__VA_ARGS__)  
  12. #else  
  13. #define DEBUG(format,...)  
  14. #endif  
  15. int main()  
  16.     char str[]="Hello World" 
  17.     DEBUG("A ha, check me: %s",str);  
  18.     return 0;  
  19. }  

测试结果:


本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

__FILE__    __LINE__ 的相关文章

  • 如何判断一个点是否属于某条线?

    如何判断一个点是否属于某条线 如果可能的话 示例值得赞赏 在最简单的形式中 只需将坐标代入直线方程并检查是否相等 Given Point p X 4 Y 5 Line l Slope 1 YIntersect 1 代入 X 和 Y Y Sl
  • 获取文件的上次访问时间

    我知道使用File对象我们可以获得最后修改时间File i e 文件 lastModified https docs oracle com javase 8 docs api java io File html lastModified 但
  • 如何在没有io的情况下在windows上创建特定大小的文件?

    Windows 上是否有与 posix fallocate 等效的函数 具体来说 我正在寻找一种方法来立即 无需执行大量 IO 创建特定大小的文件 我不关心内容 我尝试过 chsize s 它确实分配了文件 但需要很长时间 如果我右键单击文
  • 在Android上保存文件时避免因中断而丢失数据?

    我想知道其他人在 Android 上保存文件时使用什么策略来避免数据丢失 我有几个游戏应用程序 本质上 它们可能会在用户暂停 onPause 时保存游戏状态 保存游戏 这在 99 99 的情况下有效 但每隔一段时间我就会收到一个保存游戏的例
  • 旋转后获取线的新位置

    我需要在一条线上使用 RotateTransform 方法找到旋转后线的新坐标 例如 在这一行之后 line RenderTransform new RotateTransform 25 0 0 line X1其他三个属性不会改变 我找到了
  • 是否可以防止出现文件对话框?为什么?

    假设我有输入 类型 文件 元素 我想拦截 onclick 事件并防止在不满足条件时出现文件对话框 是否可以 如果不是的话 为什么 Soufiane 的代码要求您的页面上有一个名为 jQuery 的 Javascript 库 如果您没有 您可
  • Linux shell 命令逐块读取/打印文件

    是否有一个标准的 Linux 命令可以用来逐块读取文件 例如 我有一个大小为 6kB 的文件 我想读取 打印第一个 1kB 然后是第二个 1kB 看来猫 头 尾在这种情况下不起作用 非常感谢 你可以这样做read n在循环中 while r
  • java IO将一个文件复制到另一个文件

    我有两个 Java io File 对象 file1 和 file2 我想将 file1 的内容复制到 file2 有没有一种标准方法可以做到这一点 而无需我创建一个读取 file1 并写入 file2 的方法 不 没有内置方法可以做到这一
  • Restlet 和 MULTIPART_FORM_DATA 或通过 Restlet 将文件放在 Google App Engine 上的其他方式

    我尝试通过 Restlet 接收文件 但只获得完整的 MULTIPART FORM DATA 如何提取我的特定文件 我找到了一些代码块 但它们的类型不可用 RESTlet 如何处理多部分 表单数据请求 https stackoverflow
  • 将 PHP 变量保存到文本文件

    我想知道如何将 PHP 变量保存到 txt 文件 然后 再次检索它们 Example 有一个输入框 提交后写的东西 输入框将被保存到文本文件中 稍后需要结果 作为变量带回 假设变量是 text I 需要将其保存到文本文件并能够将其检索回来
  • 文件保存在文件系统中 VS 保存在数据库中

    我正在设计一个 servlet 或 Struts2 中的操作 用于文件 图像 文档等 下载 但我想知道哪种更好的方法可以将文件保留在文件系统和数据库中 只需保留文件的路径或将文件保留在数据库中 如 BLOB 我知道当我查询数据库时 哪里的
  • C++ 输出到文本文件时换行符[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 这只是一个简单的问题 但我正在尝试将
  • 如何在 Android '/data/data/pkg/files' 目录中创建文件层次结构?

    我尝试在 Android 的 data data pkg files 目录中创建 foo bar txt 这似乎是文档中的矛盾 要写入文件 请使用名称和路径调用 Context openFileOutput http developer a
  • 单击一次文件丢失

    将 Clickonce 与 VS 2010 和 NET Framework Client profile 3 5 一起使用 我有几个文件夹 其中包含运行时所需的应用程序级 XML 和 或文本文件 这些文件夹位于要使用它们的同一项目中 这些文
  • 是否可以使用.NET 跟踪文件操作?

    当以某种方式调用文件操作 例如打开或关闭 时 我是否可以在操作系统继续请求之前处理它 如果可能的话可以通过以下方式取消它 NET http en wikipedia org wiki NET Framework 如果 NET没有这样的能力
  • 从通知中打开文件

    我从服务器下载一个文件 对于此操作 我显示了进度不确定的通知 下载文件后 我想通过单击通知来打开它 我获得了扩展名并尝试使用以下命令打开它intent像这样 public static Intent openFile Context con
  • Excel VBA 导出到文本文件。需要删除空行

    我有一个工作簿 使用以下脚本将其导出到文本文件 它工作正常 但是当我打开文本文件时 末尾总是有一个空行 这导致我在生成此文本文件后运行的另一个脚本出现问题 有关如何从导出中删除空行的任何帮助 Code Sub Rectangle1 Clic
  • 如何使用 PHP 查找目录中的前 5 个文件?

    如何使用 PHP 列出按字母顺序排序的目录中的前 5 个文件或目录 Using scandir array slice array filter scandir path to dir is file 0 5 The array filte
  • 从文本文件 PHP 读取数据

    我只是想知道如何在 php 中读取文本文件 我想让它显示文本文件中的最后 200 个条目 每个条目都在一个新行上 Like John White Jane Does John Does Someones Name 等等 Thanks Use
  • 使用python将json和文件发送到flask

    我遇到这个问题 我试图在单个函数中向 Flask API 发送 接收一些文件和 JSON 在我的客户端 发件人 上我有 my json to be sent datas var1 var1 var2 var2 my file to be s

随机推荐

  • shell 脚本常用命令,音频提取、格式转换、切割

    实现一下功能 xff1a 1 xff0c mp4 视频文件提取 wav xff0c pcm xff1b 2 xff0c wav 切割为每段30s 的音频 xff1b 3 xff0c wav 切割后的音频转换为 pcm xff0c ffmpe
  • windows7下cmd窗口使用ssh登录服务器(云、本地)

    windows7下cmd窗口使用ssh命令 xff1a xff08 百度经验 xff09 https www baidu com link url 61 ZwN3UgM b6ZG9CHEGvnad7FMmefCQvSbp4QEMjf8DCL
  • wine 安装(ubuntu中安装windows下软件)

    wine xff1a 能够在多种 POSIX compliant 操作系统 xff08 诸如 Linux xff0c Mac OSX 及 BSD 等 xff09 上运行 Windows 应用的兼容层 https baike baidu co
  • 将自己的 ubuntu 系统制作为ISO镜像

    自己的Ubuntu做了很多设置 xff0c 比如各种软件包 xff0c 各种自定义的配置 如果想要在其他电脑上也安装一个一样的系统 xff0c 可以制作ISO镜像 ISO镜像可以用于发布系统 xff0c 也可以用来作为系统备份使用 以下是使
  • matlab:错误使用 fread 文件标识符无效。使用 fopen 生成有效的文件标识符。

    fidin xff1a 1 000000 错误使用 fread 文件标识符无效 使用 fopen 生成有效的文件标识符 出错 convert1 line 12 A 61 fread fidin inf 39 int16 39 以二进制形式读
  • 使用循环语句输出空心金字塔

    n 61 5 选择打印层数 for i 61 1 i lt 61 n i 43 43 for k 61 1 k lt 61 n i k 43 43 打印空格 echo 34 34 for j 61 1 j lt 61 2 i 1 j 43
  • 关于编程语句i++与++i的区别用法

    首先我们定义一个变量i xff0c int i 61 5 xff1b 然后我们做执行printf xff08 d xff0c i 43 43 xff09 xff1b 我们会发现输出结果是5 是为什么呢 xff0c 我们要搞清楚printf
  • eclipse出现 Some character…

    原文地址 xff1a eclipse出现 Some characters cannot be mapped using 34 GBK 34 character encoding 错误 作者 xff1a 赫西尼 Window gt Profe
  • php实现二维数组转置

    arr 61 array array 1 2 3 array 4 5 6 for i 61 0 i for j 61 0 j arr1 j i 61 arr i j for k 61 0 k for l 61 0 l echo arr1 k
  • PX4在GAZEBO仿真中加载iris模型问题

    目录 1 PX4启动仿真的launch系列文件1 1 单个launch文件解读1 2 对iris模型添加相机1 3 bashrc环境变量问题 2 一些Bug2 1 我的台式机无法加载模型2 1 1 若使用 96 v1 9 2版本 96 2
  • Springboot应用中设置Cookie的SameSite属性

    转载自https springboot io t topic 2602 一 Cookie除了key和value以外有几个属性 httpOnly 是否允许js读取cookiesecure 是否仅仅在https的链接下 xff0c 才提交coo
  • TCP如何保证可靠性,TCP如何实现可靠性传输的

    tcp 如何保证可靠性 大家都知道TCP是可靠性传输协议 xff0c 既然是可靠的 xff0c 就需要解决比如包丢失了 数据被破坏了 包重复了 乱序了等等这样的问题 下面将从几个方面介绍TCP的可靠性 1 校验和 TCP每一段报文都有校验和
  • php中标准使用类的方法

  • php复选框中获取文本框、密码域、…

    复选框能够进行项目的多项选择 xff0c 浏览者在填写一些表单时 xff0c 有时需要选择多个项目 xff08 如 xff1a 兴趣爱好等 xff09 复选框一般是多个同时存在 xff0c 为了便于传值 xff0c name的名字可以定义为
  • php页面js隐藏域的运用

    好聪明 四则运算 计算矩形 请输入第二个数 请选择运算符 43 请输入长请输入宽 请输入第一个数 好聪明 四则运算 计算矩形 请输入第一个数请输入第二个数请选择运算符 43 点击按钮 xff0c 可切换不同页面
  • mysql 空值,null与not null

    可以的 原文地址 xff1a mysql 空值 xff0c null与not null 作者 xff1a 五月jks gyS mysql探究之null与not null 1 我字段类型是not null xff0c 为什么我可以插入空值 2
  • 解决Missing argument 1 for…

    原文地址 xff1a 解决Missing argument 1 for DataTest testAdd 作者 xff1a 晨风 在使用PHPUnit的DataProvider方法时 xff0c 按官方帮助文档所说编写测试脚本如下 xff1
  • 色彩 标准卡大全及配色方案

    原文地址 xff1a 色彩 标准卡大全及配色方案 作者 xff1a 刘义0 配色方案浅析 一 红色的色感温暖 xff0c 性格刚烈而外向 xff0c 是一种对人刺激性很强的色 红色容易引起人的注意 xff0c 也容易使人兴奋 激动 紧张 冲
  • php中define()函数和defined…

    原文地址 xff1a php中define 函数和defined 函数的使用 及来防止恶意调用 作者 xff1a 疯子的博客 php中define 函数和defined 函数的使用 define 用来定义常量 xff0c 常量也是全局范围的
  • __FILE__    __LINE__

    我们在写程序的时候 xff0c 总是或多或少会加入一些printf之类的语句用于输出调试信息 xff0c 但是printf语句有个很不方便的地方就是当我们需要发布程序的时候要一条一条的把这些语句删除 xff0c 而一旦需要再次调试的时候 x