封装日志打印函数,具有如下功能:
- 日志所打印时的时间
- 支持不定项参数
- 日志所在的文件和行号
/********** < base_common.h base_common.c > *********/
#include <time.h> /* time(); localtime_r(); */
#include <stdarg.h> /* va_list; va_start(); va_end();
/**>1: type definition; */
typedef char CHAR;
typedef unsigned long ULONG;
typedef void VOID;
/**>2: parameters type; */
#define IN
#define OUT
#define INOUT
VOID Base_Common_Log(IN ULONG ulFileLine, IN CHAR *pcFileName, IN CHAR *pcFormat, ...)
{
time_t tmSeconds = time(0);
struct tm stNowTime;
va_list stArgs;
localtime_r(&tmSeconds, &stNowTime);
printf("[%d-%d-%d %d:%d:%d]", stNowTime.tm_year + 1900, stNowTime.tm_mon + 1,
stNowTime.tm_mday, stNowTime.tm_hour, stNowTime.tm_min, stNowTime.tm_sec);
printf("[%s-%lu]", pcFileName, ulFileLine);
va_start(stArgs, pcFormat);
vprintf(pcFormat, stArgs);
va_end(stArgs);
printf("\n");
return;
}
/********************< ctrl_main.c >*******************/
#define MAIN_LOG(format, args...) \
Base_Common_Log(__LINE__, __FILE__, format, ##args)
int main(int argc, char *argv[])
{
int i = 99;
char *pc = "hello world";
MAIN_LOG("%s %d", pc, i);
return 0;
}
>>:[2017-9-24 21:58:24][ctrl_main.c-28]hello world 99
需要运用以下知识:
1.可变参数的宏定义。
...表示参数可变,__VA_ARGS__在预处理中为实际的参数集所替换
"##"的作用是对token进行连接, format、__VA_ARGS__、args即是token。
#define LOG(format, ...) fprintf(stdout, format, ##__VA_ARGS__)
#define LOG(format, args...) fprintf(stdout, format, ##args)
2.可变参数和输出。
#include <stdio.h>
int printf(const char *format, ...);
int fprintf(FILE *stream, const char *format, ...);
int sprintf(char *str, const char *format, ...);
int snprintf(char *str, size_t size, const char *format, ...);
#include <stdarg.h>
int vprintf(const char *format, va_list ap);
int vfprintf(FILE *stream, const char *format, va_list ap);
int vsprintf(char *str, const char *format, va_list ap);
int vsnprintf(char *str, size_t size, const char *format, va_list ap);
#include <stdarg.h>
void va_start(va_list ap, last);
type va_arg(va_list ap, type);
void va_end(va_list ap);
void va_copy(va_list dest, va_list src);
3.时间函数。
The four functions asctime(), ctime(), gmtime() and localtime() return a pointer to static data and hence are not thread-safe.
Thread-safe versions asctime_r(), ctime_r(), gmtime_r() and localtime_r() are specified by SUSv2, and available since libc 5.2.5.
#include <time.h>
char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);
struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);
struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
time_t mktime(struct tm *tm);