fprintf宏

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

参考链接:

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

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

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

debug.h

 1 #ifndef _DEBUG_H_
 2 #define _DEBUG_H_
 3
 4 #define DEBUG(info,...)  5 {                        6     FILE *fp;            7     fp = fopen("log", "a+"); 8     fprintf(fp, "%d,%s",  9             __LINE__, __func__);10     fprintf(fp,info,  __VA_ARGS__);11     fclose(fp);         12 }
13
14 #endif

debug.c

1 #include <stdio.h>
2 #include "debug.h"
3
4 int main()
5 {
6     DEBUG("hello\n");
7     return 0;
8 }

编译

gcc debug.c

出现如下问题

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

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

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

 1 #ifndef _DEBUG_H_
 2 #define _DEBUG_H_
 3
 4 #define DEBUG(info,...)  5 {                        6     FILE *fp;            7     fp = fopen("log", "a+"); 8     fprintf(fp, "%d,%s",  9             __LINE__, __func__);10     fprintf(fp,info, ## __VA_ARGS__);11     fclose(fp);         12 }
13
14 #endif

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

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

 1 #ifndef _DEBUG_H_
 2 #define _DEBUG_H_
 3
 4 #define DEBUG(...)  5 {                        6     FILE *fp;           \
 7     fp = fopen("log", "a+"); 8     fprintf(fp, "%d,%s",  9             __LINE__, __func__);10     fprintf(fp,__VA_ARGS__);11     fclose(fp);         12 }
13
14 #endif

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

但是当可变参为零,即

DEBUG();

出现如下错误

时间: 2024-08-02 02:51:44

fprintf宏的相关文章

宏定义中的#,##,...,do{}while(0),__VA_ARGS__

宏定义中的#,## 1.在一个预处理器宏中的参数前面使用一个#,预处理器会把这个参数转换为一个字符数组 #define syslog(a) fprintf(stderr,"Warning: " #a"\n"); 2.简单的说,"## "是一种分隔连接方式,它的作用是先分隔,然后进行强制连接 举列 -- 试比较下述几个宏定义的区别 #define A1(name, type)  type name_##type##_type 或 #define A

宏------进阶

宏定义的黑魔法 - 宏菜鸟起飞手册 宏定义在C系开发中可以说占有举足轻重的作用.底层框架自不必说,为了编译优化和方便,以及跨平台能力,宏被大量使用,可以说底层开发离开define将寸步难行.而在更高层级进行开发时,我们会将更多的重心放在业务逻辑上,似乎对宏的使用和依赖并不多.但是使用宏定义的好处是不言自明的,在节省工作量的同时,代码可读性大大增加.如果想成为一个能写出漂亮优雅代码的开发者,宏定义绝对是必不可少的技能(虽然宏本身可能并不漂亮优雅XD).但是因为宏定义对于很多人来说,并不像业务逻辑那

C++11 新特性一增加了 __func__宏

在C11的新特性中,新增加了宏定义 __func__ 用来描述直接得到当函数的名称. 如: const char* hello() {return __func__;} //返回hello. 也可作为初始化参数传递如: struct TestStruct { TestStruct (): name(__func__){}  //返回TestStruct结构体类型. const char* name; }; __VAR_ARGS__ 表示可变参数的宏串,如下 #define LOG(...) {\

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

标准C语言预处理要求定义某些对象宏,每个预定义宏的名称一两个下划线字符开头和结尾,这些预定义宏不能被取消定义(#undef)或由编程人员重新定义.下面预定义宏表,被我抄了下来. __LINE__  当前程序行的行号,表示为十进制整型常量__FILE__  当前源文件名,表示字符串型常量__DATE__转换的日历日期,表示为Mmm dd yyyy 形式的字符串常量,Mmm是由asctime产生的.__TIME__ 转换的时间,表示"hh:mm:ss"形式的字符串型常量,是有asctime

ios 宏定义 系统版本 判定

====================================================== 当需要判断iOS系统版本的时候,相信很多人都会这么干: #define SystemVersion [[UIDevice currentDevice] systemVersion].floatValue 现在告诉屌丝们一个更好的办法就是其实系统已经做了类似的宏定义,不需要我们再去定义了 在Simulator-IOS7.0/usr/include/Availability.h中已经定义了很

宏!!!!(拷贝别人的博客的只为了收藏)

入门 如果您完全不知道宏是什么的话,可以先来热个身.很多人在介绍宏的时候会说,宏嘛很简单,就是简单的查找替换嘛.嗯,只说对了的一半.C中的宏分为两类,对象宏(object-like macro)和函数宏(function-like macro).对于对象宏来说确实相对简单,但却也不是那么简单的查找替换.对象宏一般用来定义一些常数,举个例子: //This defines PI #define M_PI 3.14159265358979323846264338327950288 #define关键

(转)iOS 常用宏定义

#ifndef MacroDefinition_h #define MacroDefinition_h //-------------------获取设备大小------------------------- //NavBar高度 #define NavigationBar_HEIGHT 44 //获取屏幕 宽度.高度 #define SCREEN_WIDTH ([UIScreen mainScreen].bounds.size.width) #define SCREEN_HEIGHT ([UI

关于宏和逗号表达式

宏是C编译系统的预处理,何谓“预”?即是正式工作开始之前的准备工作.所以宏替换是在对程序编译之前进行的~也就是直接将宏定义的字符,转换成后面的表达式. 逗号表达式:逗号运算符,优先级别最低,它将两式联接起来,可连续执行 代码:直接对文件输出1-1000的数字 #include <stdio.h> #define B P,P,P,P,P,P,P,P,P,P #define P L,L,L,L,L,L,L,L,L,L #define L I,I,I,I,I,I,I,I,I,I,N #define

linux C宏定义 转

写好C语言,漂亮的宏定义很重要,使用宏定义可以防止出错,提高可移植性,可读性,方便性等等.下面列举一些成熟软件中常用得宏定义...... 1,防止一个头文件被重复包含 #ifndef COMDEF_H #define COMDEF_H //头文件内容 #endif 2,重新定义一些类型,防止由于各种平台和编译器的不同,而产生的类型字节数差异,方便移植. typedef  unsigned char      boolean;     /* Boolean value type. */ typed