[toc]
预处理
做了什么?
example
1 2 3 4 5 6 7 8 9
| #include <stdio.h>
#define mian main #define N 1000
int mian() { printf("%d\n", N); return 0; }
|
输出了一大串代码…
是不是有一点熟悉…翻到最后的话
这下你明白了:
预处理就是字符串替换
宏
它的作用就是,把代码里以“词法单元”形式出现的 A 全都替换成 B。
1 2 3
| A.val = 1; #define A B A.val = 1;
|
预处理试试
宏函数
1
| #define foo() { return 1; }
|
宏函数可以有参数
1 2 3 4 5
| #define foo(a) { return a; }
foo(0); foo(a + b); foo(a, b);
|
可变参数
1 2 3 4 5
| #define foo(a, ...) { bar(__VA_ARGS__, a); }
foo(m); foo(m, n); foo(m, n, p);
|
普通的函数也可以有可变参数列表!(你没想过 printf 是怎么做到的吗?)
1 2 3 4
| #include <stdarg.h>
int vprintf(const char *format, va_list ap); int printf(const char *format, ...);
|
man va_args
注意点1:参数的括号与运算优先级
1 2 3
| #define add(a, b) a + b
c = d * add(a, b) * e;
|
注意点2:语法语义
1 2 3 4 5 6 7 8 9
| #define foo() bar(); baz();
if (cond) foo();
#define foo() { bar(); baz(); } if (cond) foo(); else return 0;
#define foo() do { bar(); } while(0)
|
注意点3:副作用
1 2 3
| #define max(a, b) ((a) > (b) ? (a) : (b))
max(a++, b);
|
条件编译
1 2 3 4 5 6
| #define A #ifndef A printf("A undefined!\n"); #else printf("A defined!\n"); #endif
|
条件编译也可以嵌套
1 2 3 4 5 6 7 8 9 10 11
| #define A #define B #ifdef A # ifdef B printf("A B both defined!\n"); # else printf("B undefined!\n"); # endif #else printf("A undefined!\n"); #endif
|
也可以做条件判断!
1 2 3 4 5 6
| #define A 1 #if A <= 2 printf("A <= 2!\n"); #else printf("A > 2!\n"); #endif
|
只能判断数字。如果没有指定值的话:
1 2 3 4 5 6
| #define A #if A == 0 printf("A == 0!\n"); #else printf("A != 0!\n"); #endif
|
error
但如果随便指定一个不存在的东西…
1 2 3 4 5 6
| #define A SOMESTRANGESTUFF #if A == 0 printf("A == 0!\n"); #else printf("A != 0!\n"); #endif
|
这就是玄学了(
特殊运算符
在预处理时有两个特殊的运算符。一是一元运算符 #,表示将文本替换成字符串;二是二元运算符 ##,表示将两个文本相连
1 2 3 4 5
| #define concat(a, b) a ## b #define print(a) printf(#a)
concat(hello, world); print(hello world);
|
1 2 3
| #define EVAL(expr) printf(#expr " = %d\n", expr)
EVAL(1 + 2);
|
但上面的定义有一点小问题
1 2 3 4 5
| #define this that #define concat(a, b) a ## b
int concat(this, Func)(int a, int b);
|
1 2 3 4 5 6 7
| #define this that #define concat_temp(a, b) a ## b #define concat(a, b) concat_temp(a, b);
int concat(this, Func)(int a, int b);
|
一些常用的自带宏
1 2 3 4 5 6
| __FILE__: 当前代码所处的文件名
__LINE__: 当前代码在文件中的行数 __TIME__: 当前文件在编译时的时间
__x86_64__: 是否为 X86_64 架构编译
|
1 2
| gcc -m32 a.c gcc -m64 a.c
|
1 2 3 4 5
| #define Log(fmt, ...) fprintf(stderr, "[in file %s, line %d, function %s] " fmt "\n", __FILE__, __LINE__, __func__, __VA_ARGS__)
int main() { Log("%s", "print a log"); }
|