在Linux C/C++程序中打印日志时,可能会由于需要打印未知个数的变量参数,那么vsnprintf
函数就排上用场了。这里使用一个简单的C程序例子,演示在打印源程序文件名和该打印函数所在的行号的同时,使用vsnprintf函数打印个数未知的参数变量。
代码比较简单,如果需要把内容打印在日志文件中的话,还需要调用文件处理函数。为了便于理解,这里直接把内容输出到控制台上了。需要说明的三个地方:
1 2 3 | 静态全局变量 c_FileName 和 i_FileLineNum 分别用于存储源程序文件名和打印函数所在的行号; 自定义标识符 PRINT 先调用源程序文件名和行号的赋值函数 Get_File_Line ,然后调用个数未知的参数的处理函数 F_vsnprintf; 类似于sprintf和snprintf这两个函数,相比vsprintf函数,vsnprintf加了最大字节( MAXBYTES )的限制,防止内存溢出。 |
---|
具体代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 | /** * @FileName vsnprintf_name_line.c * @Describe A simple example for using vsnprintf to print the name and line-num of source file in linux. * @Author vfhky 2016-03-13 23:28 https://typecodes.com/cseries/vsnprintffilenameline.html * @Compile gcc vsnprintf_name_line.c -o vsnprintf_name_line */ #include <stdio.h> #include <string.h> #include <stdarg.h> #define FILENAME_LEN 100 #define MAXLINE 1024 #define MAXBYTES 50 static char c_FileNameFILENAME_LEN; static int i_FileLineNum; //Self-define a function which can print the name and line-number of the source file calling it. #define PRINT Get_File_Line( __FILE__, __LINE__ );\ F_vsnprintf /** * Get the linenum and filename of the source file. * @Para-in: p_FileName: The name of the source file. * @Para-in: i_FileLine: The line-number of the source file. */ void Get_File_Line( char *p_FileName, int i_FileLine ) { strcpy( c_FileName, p_FileName ); i_FileLineNum = i_FileLine; return; } /** * Print the arguments according to the first argument, name as fmt. */ void F_vsnprintf( char *fmt, ... ) { char bufMAXLINE = {0x00}; snprintf( buf, MAXBYTES, "%s:%d ", c_FileName, i_FileLineNum ); va_list ap; va_start( ap, fmt ); vsnprintf( buf+strlen(buf), MAXLINE, fmt, ap ); va_end( ap ); strcat( buf, "\n" ); fflush( stdout ); fputs( buf, stderr ); fflush( NULL ); return; } int main( int argc, char **argv ) { PRINT( "%s", "Hello." ); PRINT( "%s %s", "Hello", "world." ); return 0; } |
---|
使用《Linux C/C++工程中可生成ELF、动/静态库文件的通用Makefile》一文中的Makefile文件进行程序编译(当然也可以使用命令进行编译gcc vsnprintf_name_line.c -o vsnprintf_name_line
),接着执行该程序,得到如下图所示的结果: