预处理, 展开头文件/宏替换/去掉注释/条件编译 (test.i main .i)
__LINE__ 表示正在编译的文件的行号
__FILE__表示正在编译的文件的名字__DATE__表示编译时刻的日期字符串,例如: "25 Dec 2007"
__TIME__ 表示编译时刻的时间字符串,例如: "12:30:55"
__STDC__ 判断该文件是不是定义成标准 C 程序 __VA_ARGS__ 是一个可变参数的宏
宏定义与函数的比较
![](https://img-blog.csdn.net/20180727185627486?watermark/2/text/aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80MTE0MzYzMQ==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70)
#pragma pack
使用指令#pragma pack (n),编译器将按照 n 个字节对齐。
使用指令#pragma pack (),编译器将取消自定义字节对齐方式。
在#pragma pack (n)和#pragma pack ()之间的代码按 n 个字节对齐。
字节对齐,我将另起炉灶,在另外一篇博客中归纳总结。
#pragma pack(push) //保存当前对其方式到 packing stack
#pragma pack(push,n) 等效于
#pragma pack(push)
#pragma pack(n) //n=1,2,4,8,16 保存当前对齐方式,设置按 n 字节对齐
#pragma pack(pop) //packing stack 出栈,并将对其方式设置为出栈的对齐
#define SQR(x) printf("The square of "#x" is %d.\n", ((x)*(x))) SQR(3)运算出来就是 The square of 3 is 9 可以看到 #x 打印出了调用的x的实际值
a##b 将a和b连接到一起
#a a被替换为字符串
例子:
#define link(a,b) a##b
#define tostr(a) #a
#define s(a) tostr(a)
printf("a and b is %s\n", tostr(link(a,b)));
printf("a and b is %s\n",s(link(a,b)));
a and b is link(a,b) 直接调用会被直接宏展开
a and b is ab 间接调用不会直接宏展开
#define my_printf2(...) printf(__VA_ARGS__)
#define my_printf3(fmt, ...) printf(fmt, __VA_ARGS__) __VA_ARGS__ 是一个可变参数的宏
#define my_printf4(fmt, ...) printf(fmt, ##__VA_ARGS__) ##__VA_ARGS__ 宏前面加上##的作用在于,当可变参数的个数为0时,这里的##起到把前面多余的","去掉的作用,否则会编译出错
2与4的功能相似,都可以接受0或者多个参数,
my_printf2("a is %d %d\n", a, aa);
my_printf2("I am chenyu \n", a);
my_printf4("I am chenyu \n");
my_printf4("a is %d\n", a);
my_printf4("a is %d %d\n", a, aa);
但是3只能接受大于等于一个参数
my_printf3("printf3 aa is %d %d\n", aa, a);
my_printf3("printf3 aa is 22 \n",aa, aa);