C语言-#和##的具体用法

c语言中,在宏里面使用’#’和’##’有它非常神奇的作用。在宏定义的替换的过程中,#号可以作为一个预处理运算符,把宏参数转换为字符串。##运算符则可以把两个宏参数组合在一起。下面就来说说具体的用法。
1、一般用法
我们使用#把宏参数变为一个字符串,用##把两个宏参数贴合在一起。
下面的代码是演示代码:
#include #define string(s)           #s#define connect(a, b)       (int)(a##e##b)int main(void){    // 输出字符串abcdefg    printf(string:%s, string(abcdefg));    // 2e3输出:2000    printf(connect:%d, connect(2,3));    return 0;}  
运行结果如下图:
2016-03-21_171313
2、当宏参数是另一个宏的时候
需要注意的是:凡是宏定义里有用'#'或'##'的地方,宏参数是不会再展开。
(1)、非’#’和’##’的情况
#include #define tow                 (2)#define mul(a,b)            (a*b)int main(void){    printf(%d*%d=%d, tow, tow, mul(tow,tow));    return 0;}  
上面代码中打印那行的宏会被展开为:
printf(%d*%d=%d, (2), (2), ((2)*(2)));  
(2)、当有'#'或'##'的时候
#include #include #define a               (2)#define str(s)          #s#define cons(a,b)       (int)(a##e##b)int main(void){    // int_max 这行会被展开为:printf(int max: %s, int_max);    printf(int max: %s, str(int_max));    // 这一行会被展开为:printf(%s, (int)(aea));    printf(%s, cons(a, a));    return 0;}  
上面的代码在编译时会失败,int_max和a都不会再被展开,然而解决这个问题的方法也很简单。加多一层中间转换宏。加这层宏的用意是把所有宏的参数在这层里全部展开,那么在转换宏里的那一个宏(_str)就能得到正确的宏参数。
#include #include #define a               2#define _str(s)         #s#define str(s)          _str(s) // 转换宏#define _cons(a,b)      (int)(a##e##b)#define cons(a,b)       _cons(a,b) // 转换宏int main(void){    // int_max,int型的最大值,为一个变量    printf(int max: %s, str(int_max));    printf(cons(a, a):%d, cons(a, a));    return 0;}  
其中代码:
printf(int max: %s, str(int_max));  
输出为:int max: 2147483647,str(int_max) ---> _str(2147483647) 然后再转换成字符串。
第二个输出代码:
printf(cons(a, a):%d, cons(a, a));  
输出为:cons(a, a):200,cons(a, a) ---> _cons(2, 2) ---> int(2e2) 。
3、'#'和'##'的一些应用特例
(1)、合并匿名变量名
#include #define ___anonymous1(type,var,line)    type   var##line#define __anonymous0(type, line)        ___anonymous1(type, _anonymous, line)#define anonymous(type)                 __anonymous0(type, __line__)int main(void){    anonymous(static int);    _anonymous9 = 666;    printf(_anonymous9:%d, _anonymous9);    return 0;}  
上述代码:anonymous(static int);最终展开为:static int _anonymous9; // 9表示该行行号;,下面分析下具体的展开过程:
第一次展开:anonymous(static int);   --->   __anonymous0(static int, __line__);;
第二次展开:__anonymous0(static int, __line__);   --->   ___anonymous1(static int, _anonymous, 9);;
第三次展开:___anonymous1(static int, _anonymous, 9);    --->   static int   _anonymous9;;
对于宏的展开过程,每次只能解开当前层的宏,所以__line__在第二层才能被解开。
(2)、获取文件名
#include #define _get_filename(filename)         #filename#define get_filename(filename)          _get_filename(filename)int main(void){    char filename[] = get_filename(__file__);    printf(filename:%s, filename);    return 0;}  
当然了,上述的宏也可以获取__date__,__line__等宏实际对应的值,上面专门定义了一个数组来存储转换后的值,实际使用时是否定义数组可自行安排。


石墨烯增强铜基复合材料制备工艺及性能的研究进展
树莓派忘记密码了?四步重设密码
Nixie PC仪表的制作
什么是 LoRaWAN® 网关?它们如何应用于物联网应用中
元宇宙的六大技术支撑及军事应用
C语言-#和##的具体用法
强力巨彩正在建立国内较大规模的高端LED显示屏产业园
对于机器学习,到底该选择哪种编程语言
OPPOR9s撩妹技术满分!论俘获芳心还是OPPO最有招
温湿度记录仪在生活中的应用有哪些?
阿童木机器人正式对外宣布完成融资超3千万元
继电器在有刷直流电机控制中有何应用?
华为Mate10什么时候上市?最新消息:华为Mate10成iPhone8最大竞争对手,你会选谁呢?
智能镜面电视让家居系统实现了智能化的升级
华为p50和华为mate40哪个好
无线路由器的WiFi带机量与什么因素有关
ST提供三相电机驱动器设计平台
开发板产生不同频率声音的程序(两个定时器的使用)
京东首次披露大快消事业群发展路线图:构建快消生态链
AI时代刚刚来临 国内AI公司更看重未来资源的布局与AI生态的建设