linux c 宏 文件名,C语言标准宏获取文件名、行号、函数名的方法以及#和##的用法...
一、前言在后台程序运行出问题时,需要查看详尽的日志,C语言提供记录日志触发点文件名、行号、函数名的方法,关键是利用C99新增的预处理标识符__VA_ARGS__;先介绍几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。二、ANSI C标准宏__LINE__//在源代码中插入当前源代码行号__FILE__//在源...
一、前言
在后台程序运行出问题时,需要查看详尽的日志,C语言提供记录日志触发点文件名、行号、函数名的方法,关键是利用C99新增的预处理标识符__VA_ARGS__;先介绍几个编译器内置的宏定义,这些宏定义不仅可以帮助我们完成跨平台的源码编写,灵活使用也可以巧妙地帮我们输出非常有用的调试信息。
二、ANSI C标准宏
__LINE__ //在源代码中插入当前源代码行号
__FILE__ //在源文件中插入当前源文件名
__DATE__ //在源文件中插入当前的编译日期
__TIME__ //在源文件中插入当前编译时间
__STDC__ //当要求程序严格遵循ANSI C标准时该标识被赋值为1
__cplusplus //当编写C++程序时该标识符被定义
_WIN32//在程序运行在windows系统上被定义位1
linux //在程序运行在linux系统上被定义位1
__x86_64__ //在程序运行在64位系统上被定义位1
__i386__ //在程序运行在32位系统上被定义位1
__VA_ARGS__//是一个可变参数的宏,这个可宏是新的C99规范中新增的,//目前似乎gcc和VC6.0之后的都支持(VC6.0的编译器不支持)。//宏前面加上##的作用在于,可以接受参数为0个或者多个
三、实例
宏实例:
#include
intmain()
{
printf("__func__:%s\n", __func__);
printf("__FILE__:%s\n", __FILE__);
printf("__DATE__:%s\n", __DATE__);
printf("__TIME__:%s\n", __TIME__);
printf("__LINE__:%d\n", __LINE__);return 0;
}
宏实例程序输出如下:
__func__:main
__FILE__:main.c
__DATE__:Sep14 2019__TIME__:14:26:36__LINE__:9
四、#和##运算符
其中#和##运算符的功能有所不同,在这里也做一定的介绍
1. #用来把参数转换成字符串
实例1:
#define P(A) printf("%s:%d\n", #A, A);
intmain()
{int a = 1, b = 2;
P(a);
P(b);
P(a+b);return 0;
}
实例1程序输出如下:
a:1b:2a+b:3
实例2:
#define SQUARE(x) printf("The square of "#x" is %d.\n", ((x)*(x)))
intmain()
{
SQUARE(8);return 0;
}
实例2程序输出如下:
The square of 8 is 64
2. ##运算符可以用于宏函数的替换部分
##就是个粘合剂,将前后两部分粘合起来,也就是有“组成变量名”的意思。特别要和#运算符的功能区分开来,#是连接字符串,而##是连接变量名。
但是“##”不能随意粘合任意字符,必须是合法的C语言标示符。在单一的宏定义中,最多可以出现一次“#”或“##”预处理操作符。如果没有指定与“#”或“##”预处理操作符相关的计算次序,则会产生问题。为避免该问题,在单一的宏定义中只能使用其中一种操作符(即,一份“#”或一个“##”,或都不用)。除非非常有必要,否则尽量不要使用“#”和“##”。
实例程序:
#include
#define XNAME(n) SYSTEM_ ## n
intmain()
{int SYSTEM_ = 0,
SYSTEM_OPEN= 1,
SYSTEM_WRITE= 2,
SYSTEM_CLOSE= 3;
printf("%d\n", XNAME());
printf("%d\n", XNAME(OPEN));
printf("%d\n", XNAME(WRITE));
printf("%d\n", XNAME(CLOSE));return 0;
}
实例程序输出:
0
1
2
3
此外,__VA_ARGS__ 是一个可变参数的宏,很少人知道这个宏,这个可变参数的宏是新的C99规范中新增的,目前似乎只有gcc支持(VC6.0的编译器不支持)。实现思想就是宏定义中参数列表的最后一个参数为省略号(也就是三个点)。
##__VA_ARGS__ 宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的逗号去掉的作用,否则会编译出错,相当于能够接受0个及以上的参数。
##__VA_ARGS__的实例:
#define my_print1(fmt,...) printf(fmt, __VA_ARGS__)my_print1("iiijjj\n") //错误打印
my_print1("i=%d,j=%d\n",i,j) //正确打印
#define my_print2(fmt,...) printf(fmt, ##__VA_ARGS__)my_print2("iiijjj\n") //正确打印
my_print2("i=%d,j=%d\n",i,j) //正确打印
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)