文章目录
1,防止一个头文件被重复包含
#ifndef BODYDEF_H
#define BODYDEF_H
//头文件内容
#endif
2,得到指定地址上的一个字节或字
#define MEM_B( x ) ( *( (char* ) (x) ) )
#define MEM_W( x ) ( *( (short* ) (x) ) )
3,得到一个field在结构体(struct)中的偏移量
#define FPOS( type, field ) ( (int) &(( type *) 0)->field )
4,使用一些宏跟踪调试
__LINE__ (两个下划线),对应%d
__FILE__ 对应%s
__DATE__ 对应%s
__TIME__ 对应%s
#include <stdio.h>
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
// __VA_ARGS__ 为("..."对应的内容)
int main(void)
{
// 输出为
// Dec 1 2021,05:12:28
debug("%s,%s\n", __DATE__, __TIME__);
return 0;
}
5,字符串化# 和 宏连接符##
6,常用于内核的填充结构相关代码
#define FILL(a) {a, #a}
enum IDD{OPEN, CLOSE};
typedef struct MSG{
IDD id;
const char * msg;
}MSG;
MSG _msg[] = {FILL(OPEN), FILL(CLOSE)};
// 相当于:
// MSG _msg[] = { {OPEN, "OPEN"}, {CLOSE, "CLOSE"} };
7,可变参数传递
__VA_ARGS__
__VA_ARGS__
就是"..." 表示的内容
如
#define debug(format, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
在GCC中也支持这类表示, 但是在G++ 中不支持这个表示.
例程
#include <stdio.h>
#define debug(fmt, ...) fprintf(stderr, fmt, ##__VA_ARGS__)
// __VA_ARGS__ 为("..."对应的内容)
int main(void)
{
// 输出:Dec 1 2021,05:12:28
debug("%s,%s\n", __DATE__, __TIME__);
return 0;
}
上面例程中,
debug(fmt, ...)
既可以输出指定内容,如 debug("666");
;此时 … 所指代的内容为空
也可以格式化输出内容:debug("%s,%s", __DATE__, __TIME__);
。
还有一种 gcc 下的可变参数传递
#define pr_info(fmt, arg...) \
printk(KERN_INFO fmt, ##arg)
例程如下:
#include <stdio.h>
#define pr1(fmt, arg...) \
printf(fmt, ##arg)
#define pr2(fmt, ...) \
printf(fmt, ##__VA_ARGS__);
int main(void)
{
printf("%s(%d):\n", __FILE__, __LINE__);
pr1("%d\n", 666666);
pr2("%d\n", 88888888);
printf("%s(%d):\n", __FILE__, __LINE__);
return 0;
}
编译运行:
jl@jl-virtual-machine:~/test$ ./a.out
test.c(11):
666666
88888888
test.c(14):