最近在调试程序,使用printf函数和调试信息都不能在终端输出,所以使用比较笨的方法。将调试信息写到文件中,再查看文件。由于要多次使用fprintf函数,所以将其写成宏。

参考链接:

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

“…”表示零个或多个参数,后面使用__VA_ARGS__把参数传递给宏。当宏的调用展开时,实际的参数就传递给 fprintf()了。

将宏定义成一个函数,这样一来每次都会执行一次完成的操作,当在同一个函数内部多次使用同一个宏的时候,其中函数定义的局部变量不会和其他的函数冲突,如果不定义成函数的话,编译器就会报错。

debug.h

 #ifndef _DEBUG_H_
#define _DEBUG_H_ #define DEBUG(info,...) \
{ \
FILE *fp; \
fp = fopen("log", "a+");\
fprintf(fp, "%d,%s", \
__LINE__, __func__);\
fprintf(fp,info, __VA_ARGS__);\
fclose(fp); \
} #endif

debug.c

 #include <stdio.h>
#include "debug.h" int main()
{
DEBUG("hello\n");
return ;
}

编译

gcc debug.c

出现如下问题

而将main函数中更改,增加一个参数。改为DEBUG("hello\n",123);

再次编译,编译通过,运行程序,查看生成的文件,已经将内容写到里面。

上网查阅,解决问题方法1,可变参数前面加上“##”,如果可变参数为空,那么“##”可以使编译器去掉前面的空格。

 #ifndef _DEBUG_H_
#define _DEBUG_H_ #define DEBUG(info,...) \
{ \
FILE *fp; \
fp = fopen("log", "a+");\
fprintf(fp, "%d,%s", \
__LINE__, __func__);\
fprintf(fp,info, ## __VA_ARGS__);\
fclose(fp); \
} #endif

当可变参为零,DEBUG("hello\n");编译通过。

解决方法2,更改宏如下所示,再次只打印一个字符串就,不会有问题。

 #ifndef _DEBUG_H_
#define _DEBUG_H_ #define DEBUG(...) \
{ \
FILE *fp; \
fp = fopen("log", "a+");\
fprintf(fp, "%d,%s", \
__LINE__, __func__);\
fprintf(fp,__VA_ARGS__);\
fclose(fp); \
} #endif

DEBUG("hello\n");编译通过,

但是当可变参为零,即

DEBUG();

出现如下错误

fprintf宏的更多相关文章

  1. iOS之常用宏定义

    下面我为大家提供一些常用的宏定义! 将这些宏定义 加入到.pch使用 再也不用 用一次写一次这么长的程序了 //-------------------获取设备大小------------------- ...

  2. Linux C 文件输入输出函数 fopen()、getc()/fgetc()、putc()/fputc()、fclose()、fprintf()、fscanf()、fgets()、fputs()、fseek()、ftell()、fgetpos()、fsetpos() 详解

      fopen(打开文件) 定义函数 FILE * fopen(const char * path,const char * mode); 函数说明 参数path字符串包含欲打开的文件路径及文件名,参 ...

  3. c++宏使用总结【转】

    C/C++中宏总结C程序的源代码中可包括各种编译指令,这些指令称为预处理命令.虽然它们实际上不是C语言的一部分,但却扩展了C程序设计的环境. ANSI标准定义的C语言预处理程序包括下列命令:  #de ...

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

    __VA_ARGS__ 是一个可变参数的宏(gcc支持).实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点).这样预定义宏_ _VA_ARGS_ _就可以被用在替换部分中,替换省略号所 ...

  5. 可变参数宏__VA_ARGS__

    在 GNU C 中,宏可以接受可变数目的参数,就象函数一样,例如:#define pr_debug(fmt,arg...) \printk(KERN_DEBUG fmt,##arg) 用可变参数宏(v ...

  6. 关于标准C语言的预定义宏【转】

    标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来. __LINE__  当 ...

  7. C语言宏定义时#(井号)和##(双井号)的用法

    C语言中如何使用宏C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念).下面对常遇到的宏的使用问题做了简单总结. 关于#和## 在C语言的宏中,#的功能是将其后面 ...

  8. iOS中常见的一些宏

    原文链接 1.处理NSLog事件(开发者模式打印,发布者模式不打印) #ifdef DEBUG #define NSLog(FORMAT, ...) fprintf(stderr,"%s:% ...

  9. iOS - 常用的宏定义

    1.处理NSLog事件(开发者模式打印,发布者模式不打印) 1 2 3 4 5   #ifdef DEBUG   #define NSLog(FORMAT, ...) fprintf(stderr,& ...

随机推荐

  1. python 小游戏之摇骰子猜大小

    最近学习Python的随机数,逻辑判断,循环的用法,就想找一些练习题,比如小游戏猜大小,程序思路如下: 开发环境:python2.7 , 附上源代码如下: 摇骰子的函数,这个函数其实并不需要传任何参数 ...

  2. POJ 1789:Truck History(prim&amp;&amp;最小生成树)

    id=1789">Truck History Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 17610   ...

  3. 调用oracle 各种报错总结---待续

    ORA-01747: user.table.column, table.column 或列说明无效 原因之一是sql语句拼接错误,多了逗点:二是使用到了oracle的关键字所致 ORA-02449: ...

  4. Ubuntu下设置环境变量

    Ubuntu下设置环境变量有三种方法,一种用于当前终端,一种用于当前用户,一种用于所有用户:   一:用于当前终端: 在当前终端中输入:export PATH=$PATH:<你的要加入的路径&g ...

  5. mysql-5.7 saving and restore buffer pool state 详解

    一.mysql 重启要面临的问题: 由于重启后之前innodb buffer pool中缓存的数据就都没有了,如果这个时候业务SQL来临,mysql就只能是从磁盘中 读取数据到内存:可能要经过数个小时 ...

  6. JAVA class 编译jar。 控制台使用jar

    //编译jar jar -cvf  -mgtvEncode.jar -mgtvEncode.class //使用jar java -cp mgtvEncode.jar mgtvEncode

  7. ps换衣服

    1.抠衣服->给衣服新建图层(ctrl+j)->给图层去色,让衣服边黑白色.2.剪贴蒙版(上图:大花布,下形:衣服).作用:大花布替换成衣服3.大花布图层->叠加图层样式或其它图层样 ...

  8. dia无法输入中文?

    解决方法: 以管理员权限打开/usr/bin/dia ,做如下修改 #dia-gnome --integrated "$@" dia-gnome "$@"

  9. sqlite时间戳转时间语句(时间转时间戳)实例

    sqlite时间戳转时间.时间转时间戳的方法 实现代码: sqlite, 'unixepoch', 'localtime'); +----------------------------------- ...

  10. mysql执行计划介绍

    简单讲讲mysql的执行计划,只列出了一些常见的情况,希望对大家有所帮助   烂sql不仅直接影响sql的响应时间,更影响db的性能,导致其它正常的sql响应时间变长.如何写好sql,学会看执行计划至 ...