预处理指令
预处理指令
程序员所编写的c代码并不能直接被编译,而是需要一段程序预先翻译成标准的c代码,负责处理的程序就叫预处理器,翻译的过程就叫做预处理,被翻译的代码就叫做预处理指令,所有预处理指令都是以#开头
gcc -E file.c 把预处理结果显示在屏幕上
gcc E file.c -o file.i 把预处理结果输出到文件上
include 把头文件插入当前文件中
#include<> 从系统指定的路径下查找头文件,并插入当前文件中。
#include"" 先从当前路径下查找头文件,如果没有再从系统指定路径下查找头文件,然后再插入当前文件中。
define 宏定义指令
定义号宏常量
#define 宏名 (字面值)
注意:末尾不要加分号
作用:用标识符来替代字面值数据,从而提高代码的可读性,可扩展性。
代码在预处理时所使用的宏名会被替换成字面值。
#define 宏名(a,b,c) (a+b+c)
不是真正的函数,而是在使用了带参数的宏,预处理时使用了带参宏的位置替换成宏名后面的语句,所提供的的参数也会被替换到语句中的位置。
优点:
- 不是真正的函数调用,没有参数传递过程,也没有返回值
- 不限制参数类型,任何类型都可以使用,代码的通用性强
缺点:
- 没有类型检查,安全性低
- 过多使用会造成代码冗SW余,导致代码段增大,浪费内存。
- 可能会有二义性(多加点括号)
定义宏函数要注意的问题:
- 给每个参数加一个小括号,避免产生二义性
- 使用小括号、大括号包含整个宏函数代码,进行保护
- 宏函数不能换行可以使用续行符 \ 来分行一下,但是还是一行
- 宏函数参数不要使用自变运算符。
练习
定义一个交换两个变量的宏函数,要任何类型的变量都可以使用
the first way
#define swap(a,b,type) { \
type t=a; \
a=b; \
b=t; \
}
the second way
#define swap(a,b) {typeof(a) t=a; a=b; b=t;}
在编译时也可以定义宏:
gcc -D DEBUG
预定义好的宏:
func 获取函数名
FILE 获取文件名
LINE 获取当前行号
DATE 获取当前日期
TIME 获取当前时间
__cplusplus 变量只在c++中编译,判断是不是在c++环境中
删除宏
undef 宏名
条件判断
if , #ifdef , #ifndef , #else , #elif , #endif
头文件卫士
#ifndef、#define、#endif 防止头文件被重复包含
代码注释
//单行注释,使用麻烦,早期的编译器不支持
/*不能嵌套使用 */ 不能嵌套使用
if 0|1
适合注释大段代码
endif
判断代码的编译、运行的环境:
ifdef _cplusplus
printf("C++编译器")
#else
printf("C编译器")
#endif
if defined(APPLE)
puts("我用的是mac os");
#elif defined(WIN32) || defined(_WIN32) || defined(WIN32)
puts("我用的是windows os");
#elif defined(linux)
puts("我用的是linux os");
#endif
用于调试程序的DEBUG函数:
#ifdef DEBUG
#define debug(fmt,...)\
{\
printf("File:%s Line:%u Func:%s Info:",__FILE__,__LINE__,__func__);\
printf("\033[01;34m");\
printf("fmt,##__VA_ARGS__");\
printf("\033[00m\n");\
}
#else
#define debug(fmt,...) if(0)
#endif

浙公网安备 33010602011771号