带可变参数的宏函数和普通函数实现

From: http://www.vimer.cn/2010/03/cc%E5%AE%8F%E5%AE%9A%E4%B9%89%E7%9A%84%E5%8F%AF%E5%8F%98%E5%8F%82%E6%95%B0.html


编写代码的过程中,经常会输出一些调试信息到屏幕上,一般会调用printf这类的函数。
但是当调试解决之后,我们需要手工将这些地方删除或者注释掉。
再这次的项目中就用到类似问题,为了调试程序,再一些地方输出了很多的信息,随着项目的调试,输出的信息越来越多。于是就面临着,如何处理这些输出信息的语句。
简单删掉,不仅有一定的工作量,而且也不能保证之后就不出现问题,出现问题后这些信息还是有用的。
不去掉,带着调试信息就上线,这是明显不允许的。
于是就想到了一个可行的办法。如下:

void myprintf(char* fmt, ...)
{
}
#ifdef DEBUG
#define printf(fmt, args...) myprintf(fmt, ##args)
#endif

调试阶段带着DEBUG调试,正式上线就可以把printf变成一个空函数了。
这样做的一个潜在风险是可能会导致默写glib函数需要调用printf输出错误log也给取消掉了。
令人欣慰的是,大部分glib调用的应该是fprintf。
虽然问题解决了,但是我对args...以及##args还是不太了解。上网找了些gcc手册的资料如下:
带有可变参数的宏(Macros with a Variable Number of Arguments)
在1999年版本的ISO C 标准中,宏可以象函数一样,定义时可以带有可变参数。宏的语法和函数的语法类似。下面有个例子:

#define debug(format, ...) fprintf (stderr, format, __VA_ARGS__)

这里,‘…’指可变参数。这类宏在被调用时,它(这里指‘…’)被表示成零个或多个符号,包括里面的逗号,一直到到右括弧结束为止。当被调用时,在宏体(macro body)中,那些符号序列集合将代替里面的__VA_ARGS__标识符。更多的信息可以参考CPP手册。
GCC始终支持复杂的宏,它使用一种不同的语法从而可以使你可以给可变参数一个名字,如同其它参数一样。例如下面的例子:

#define debug(format, args...) fprintf (stderr, format, args)

这和上面举的那个ISO C定义的宏例子是完全一样的,但是这么写可读性更强并且更容易进行描述。
GNU CPP还有两种更复杂的宏扩展,支持上面两种格式的定义格式。
在标准C里,你不能省略可变参数,但是你却可以给它传递一个空的参数。例如,下面的宏调用在ISO C里是非法的,因为字符串后面没有逗号:

debug ("A message")

GNU CPP在这种情况下可以让你完全的忽略可变参数。在上面的例子中,编译器仍然会有问题(complain),因为宏展开后,里面的字符串后面会有个多余的逗号。
为了解决这个问题,CPP使用一个特殊的‘##’操作。书写格式为:

#define debug(format, ...) fprintf (stderr, format, ## __VA_ARGS__)

这里,如果可变参数被忽略或为空,‘##’操作将使预处理器(preprocessor)去除掉它前面的那个逗号。如果你在宏调用时,确实提供了一些可变参数,GNU CPP也会工作正常,它会把这些可变参数放到逗号的后面。象其它的pasted macro参数一样,这些参数不是宏的扩展。


=================================================================================================================

From: http://lindaojiang.blog.163.com/blog/static/3498088120101124114146951/

宏定义函数带可变参数,用宏重定义printf
需要gcc c99
具体用法如下:
#include <stdio.h>
#define DBG(arg...) printf(arg)
#define DEBUGP(format, ...) printf(format, ## __VA_ARGS__)
int main(void)
{
    DBG("abc%d%s\n", 66, "yur");
    DEBUGP("abc%d%s\n", 66, "yur");
    return 0;
}

gcc -o aa aa.c
./aa

可方便的用于输出调试信息
需要输出就定义#define DBG(arg...) printf(arg),不需要输出就定义成空#define DBG(arg...)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/405654.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

SAP 免费赠与客户货物的销项税处理

免费赠与客户货物的销项税处理 如果免费赠与客户货物却要体现销项税&#xff0c;如何处理&#xff1f;在实际业务中因为免费货物是不免税的。所以大家总是以为使用0费用解决但是有一种情况是存在于视同销售。 即D&#xff1a;销售费用 C&#xff1a;销项税 SAP中的处理逻…

前端小知识点(2):普通字符串和new String有什么区别

目录 一、其实不仅字符串 二、那么到底为什么&#xff1f; 三、代码案例 四、运行结果 一、其实不仅字符串 var str abc; typeof str > string //他不是对象&#xff0c;可以有方法或者属性 var num 123; //他不是对象&#xff0c;可以有方法或者属性 typeof num …

linux更新命令yum,Linux中升级更新命令yum upgrade和yum update的区别

Linux中升级更新命令yum upgrade和yum update的区别更新时间&#xff1a;2019-10-31 17:21最满意答案Linux升级命令有两个分别是yum upgrade和yum update, 这个两个命令是有区别的:复制代码代码如下:yum -y update升级所有包同时也升级软件和系统内核复制代码代码如下:yum -y u…

Linux 管理登陆的用户/查看/剔除

Linux是多用户操作系统&#xff0c;支持多用户同时在线&#xff0c;支持对登陆用户的管理&#xff1a;查看与剔除等。 一、查看在线用户命令 命令&#xff1a; w 二、查看登录记录命令 命令 last 三、剔除在线用户命令 命令&#xff1a;sudo pkill -kill -t usr 四、pkill…

Windows下 maven3.0.4的安装步骤+maven配置本地仓库

简单讲下maven的安装步骤&#xff1a; 1.在安装maven之前&#xff0c;先确保已经安装JDK1.6及以上版本&#xff0c;并且配置好环境变量。 2.下载maven3&#xff0c;最新版本是Maven3.0.4 &#xff0c;下载地址&#xff1a;http://maven.apache.org/download.html 下载apache…

C语言日志操作类实例

包含三个主要的文件&#xff1a;joefunction.h(c), m.c(主函数文件) 1. m.c #include <stdio.h> #include <string.h> #include <time.h> #include "joefunction.h"extern FILE *g_logFile;int main(int argc, char *argv[]) {char temp[16] {0}…

ESX与ESXi管理员必备25个命令

ESX与ESXi管理员必备25个命令VMware ESX和ESXi命令这些VMware ESX和ESXi的命令可以运行在ESX服务控制台&#xff08;本地或远程使用Secure Shell&#xff09;或RCLI&#xff08;在VMware Infrastructure 3&#xff09;和vSphere CLI的&#xff08;在vSphere&#xff09;。在RCL…

前端小知识点(3):JavaScript 单线程

目录 一、为什么 JavaScript 是单线程&#xff1f; 二、JavaScript是单线程&#xff0c;怎样执行异步的代码&#xff1f; 三、事件循环机制 四、代码1 五、结果1 六、代码2 七、结果2 一、为什么 JavaScript 是单线程&#xff1f; JavaScript 语言的一大特点就是单线程…

Linux安装samba的过程,Samba安装全过程

对于linux与windows共享&#xff0c;和平共处&#xff0c;我们可以用Samba软件Samba是一套免费的开源软件&#xff0c;可以在linux或其他类unix操作系统上实现windows域控制器&#xff0c;文件服务&#xff0c;打印服务等。Samba实现了windows系统所使用的核心网络协议&#xf…

树莓派UART串口编程--使用wiringPi库-C开发【2-修改驱动】

一、前言 上一篇博文记录了使用wiringPi提供的串口驱动wiringSerial.c wiringSerial.h&#xff0c;并基于该驱动对串口进行简单的通信&#xff0c;测试中发现该串口的驱动比较简单&#xff0c;接收数据会存在分包的现象&#xff0c;另外一点是串口配置只提供了波特率参数配置&…

《软件开发计划》

校友聊项目开发计划书 项目名称&#xff1a;校友聊 1.引言 1.1编写目的 编写本文档的目的是为了校园内网的用户使用本软件进行文字&#xff0c;视频聊天&#xff0c;而不耗费内网的外网的流量。 1.2背景 基于校园内网用户对流量的强大需求&#xff0c;以及考虑到其中一些特殊用…

【转】全面理解javascript的arguments,callee,caller,call,apply概念(修改版)

(注&#xff1a;在看到大家如此关注JS里头的这几个对象&#xff0c;我试着把原文再修改一下&#xff0c;力求能再详细的阐明个中意义 2007-05-21&#xff09;在提到上述的概念之前&#xff0c;首先想说说javascript中函数的隐含参数&#xff1a;arguments Arguments 该对象代表…

windows延缓写入失败相关问题解决办法

From: http://www.ggsafe.com/news/1324547234222.shtml 我们在使用电脑时&#xff0c;有时在不正常关机后电脑会出现这样那样的问题。windows延缓写入失败就是其中一个&#xff0c;很多网友在互联网上发帖求助windows延缓写入失败怎么办&#xff0c;出现这种情况一般都是由于电…

wince linux 性能,wince remote call profiler(性能分析)

如何使用1 建立工程,CPU类型必须于目标机型一致如ARMV4I,所以选择WCE Application,然后选择empty project2 project settings 中,link页,Object/library modules中添加 cecap.lib(前面有空格),Ingore libraries中添加,libc.lib(前面有逗号).C/C页Project Options最后添加 /call…

前端小知识点(4):JS 运行机制和存储

目录 被忽视的内存管理 JS工作原理 JS代码如何运行 JavaScript内存的生命周期 栈内存、堆内存 代码案例 运行结果 被忽视的内存管理 JavaScript不像C、C等语言——程序员必须通过调用内存管理接口&#xff0c;比如 malloc()和free()&#xff0c;自己手动分配和释放内存。…

201506230818_《JavaScript权威指南(第六版)——callee和caller、对象属性用作实参、自定义函数属性》(P175-180)...

1. callee 正在执行的函数。使用方法&#xff1a;arguments.callee... caller 正在调用执行函数的函数。 2.对象属性用作实参&#xff0c;形如&#xff1a;function fn(arg) { var arg.name name || Josn, arg.age age || 60 , ... } 3. 在传入实参时候&#xff0c;宁愿在检查…

VIM选择文本块

From: http://hi.baidu.com/mykledge/blog/item/d42e4d63f57232d48cb10d6c.html 在正常模式下&#xff08;按ESC进入&#xff09;按键v进入可视化模式&#xff0c;然后按键盘左右键或h,l键即可实现文本的选择。 其它相关命令&#xff1a; v&#xff1a;按字符选择。经常使用的模…

Linux ps aux查看进程

一、ps 命令 ps 是Process Status的缩写&#xff0c;用于查看进程状态&#xff0c;ps 可以显示linux系统的所有进程信息。 用法&#xff1a; ps a 显示现行终端机下的所有程序&#xff0c;包括其他用户的程序。ps -A 显示所有程序。 ps c 列出程序时&#xff0c;显示每个程序…

2010数据库SQL Server 盘点

让我们一起来盘点一下2010数据库SQL Server 发布了那些给力的新品。 1. 微软发布SQL Server 2008 R2 微软公司于2010年4月21日宣布推出Microsoft SQL Server 2008 R2。SQL Server 2008 R2已经可以看作是本年度的一次重量级发布。微软公司努力将SQL Server打造为一个信息平台&am…

linux下有四个作业优先级,第一次作业:对Linux系统分析

一.操作系统的组成1.无进程的内核在一些操作系统当中操作系统的内核在所有的进程之外执行。也就是说操作系统有自己的内存区域和系统栈&#xff0c;当进程发生 中断&#xff0c;陷阱或系统调用时&#xff0c;此进程的上下文环境被保存在系统栈中&#xff0c;控制权转移给内…