使用宏杂技,心里一定要默念:“这是代码级的字符串替换”。换言之,宏只是替换进代码里去,就像直接写进去一样,替换完再参与编译。
1.#
转换符。#var
表示取变量名,而不是取它的值。
例子(打印变量名和变量值):
//#var表示变量名
#define debug_value(var) printf("%s:%d, ", #var, var)
使用:
#include <stdlib.h>
#include <stdio.h>
#define debug_value(var) printf("%s:%d, ", #var, var)
int main()
{
int a = 4;
int b = 5;
debug_value(a);//打印 a: 4
//debug_value(a) 替换后将变为
//printf("%s:%d, ", "a", a)
debug_value(b); //打印b: 5\n
printf("\n");
return 0;
}
==============================
[root@localhost195-46 other]# ./test
a:4, b:5,
2. ##(只能用于宏,必须直接跟字符,不能与#连用)
连接符。连接传入宏的参数的变量名 以及宏内的字符串(这个“字符串”不需要被引号括起来)。
例子:
//该宏将 x的对应变量名 与 y的对应变量名 与 23333连接起来并替换到 调用 connect(x, y)的代码位置
#define connect(x, y) x##y##23333
使用:
#include <stdlib.h>
#include <stdio.h>
#define debug_value(var) printf("%s:%d, ", #var, var)
#define connect(x, y) x##y##23333
int main()
{
int a = 4;
int b = 5;
int connect(a, b) = 32;
//上面connect(a, b)替换后将变为
//ab23333, 这一行代码替换完后即为:
//int ab2333 = 32; 这就是说定义了一个变量,变量名为ab2333
printf("%d\n", ab23333);
a = ab23333;
debug_value(a);
printf("\n");
return 0;
}
3. VA_ARGS
代表可变长参数列表。
例子:(最常用,打印调试信息)
#define debug_info(fmt,...) printf(fmt,##__VA_ARGS__)
使用:
#include <stdlib.h>
#include <stdio.h>
#define debug_value(var) printf("%s:%d, ", #var, var)
#define connect(x, y) x##y##23333
#define debug_info(fmt,...) printf(fmt,##__VA_ARGS__)
int main()
{
int a = 4;
int b = 5;
int connect(a, b) = 32;
printf("%d\n", ab23333);
a = ab23333;
debug_value(a);
printf("\n");
debug_info("%s: %d\n", "ab23333", connect(a, b));
//替换后该行变为:
//printf("%s: %d\n", "ab23333", ab2333);
return 0;
}
=============================
[root@localhost195-46 other]# ./test
32
a:32,
ab23333: 32
4. 将x向上取n的整倍数
在写内存池代码的时候很常用。分配出的内存地址需要 按4或8对齐,这样就要在上一片内存的最后字节之后找到一个4或8的整数倍地址。
#define RESIZE(x, n) ( ( x + (n-1) ) & ( ~(n-1) ) )
解读:
&(~(n-1)): n-1后安位取反再安位与。
n-1后得到的是 某数除以n后能够得到的所有余数的掩码。安位取反(余数的bit位都是0)再安位与之后,就把这个“某数”对n的余数给掩(掩码的作用)掉了。
(x+ (n-1)):就是上面所说的“某数”,加上n-1,就是向上取;如果不加n-1的话,则最后的计算结果将小于等于x,即x向下取n的整数倍。
使用:
#include <stdlib.h>
#include <stdio.h>
#define RESIZE(x, n) ( ( x + (n-1) ) & ( ~(n-1) ) )
#define debug_info(fmt,...) printf(fmt,##__VA_ARGS__)
int main()
{
int a = 4;
int b = 5;
int c = 11;
a = RESIZE(a, 4);//4
b = RESIZE(b, 4);//8
c = RESIZE(c, 4);//12
debug_info("%s: %d, %s: %d, %s: %d\n",
"a", a, "b", b, "c", c);
return 0;
}
=============================
[root@localhost195-46 other]# ./test
a: 4, b: 8, c: 12