第六章 预处理命令在c语言中所有# 开头的指令被称为预处理指令。gcc 编译预处理 所有的预处理指令都要在这步处理完汇编编译连接#include包含头文件。 全局变量的声明函数的声明 自定义构造类型声明 别名 宏名。 本质会把被包含的文件的内容复制过来。#include stdio.h #include stdio.h ,表示 在系统头文件的目录下查找。 非用户定义的头文件 。 /usr/include 编译器会先在当前目录(a.out 所在的目录)下查找头文件 在去系统目录下查找 。 不要包含.c 文件多文件编程 .c .h 的模板。#define宏定义指令宏只是代码替换中间不会进行任何数据 计算操作宏在定义的时候 尽量加圆括号 。不带参宏#define PI 3.14#define M 50// #define 宏名 宏值 // 宏值如果是一个表达式的话 最好都使用圆括号包起来 #define N ((M)(M))int main() { double r 7.1234; double area r*r *PI; printf(area is %f\n,area);int num 0 ; num N*N; // 5050 * 5050 printf(num is %d\n,num); return 0;}2.带参宏#define MAX(x,y) ((x)(y)? (x):(y)) #define MAX3(x,y,z) MAX(MAX((x),(y),(z)) #define ADD(a,b) ((a)(b)) main() { int a 10; int b 20; int ret MAX(a,b); printf(max is %d\n,ret); ret ADD(34,5); // ab 345 printf(add is %d\n,ret); }带参宏函数参数没有类型没有返回值本质代码替换有返回值参数有类型没有参数传递的概论本质就是替换。预处理阶段完成值传递地址传递实参形参消耗内存如果调用的多会导致代码变大。运行的时候加载代码只有一份。没有传参的过程没有跳转的过程。有参数传递就有内存开销。适用于 功能简单的场景功能复杂多行代码// 带参宏 #define MAX(x,y) ((x)(y)? (x):(y)) #define ADD(a,b) ((a)(b)) #define LENTH(r) (2*(PI)*(r)) #define PRINT(a,b,c) do{\ printf(a is %d\n,a);\ printf(b is %d\n,b);\ printf(c is %d\n,c);}while(0) int main() { int a 10; int b 20; int ret MAX(a,b); printf(max is %d\n,ret); ret ADD(34,5); // ab 345 printf(add is %d\n,ret); PRINT(1,2,3); return 0; }条件编译,宏开关#if #elif #else #endif #ifdef #ifndef #if 0 #if 条件 3.0 VERSION 判断条件的真假 决定#if 和#endif 之间的代码是否要预处理 #endif #define DEBUG 1 #if DEBUG 调试相关的代码 在程序调试过程中需要显示的。 如果是正式程序不需要显示 #endif #if DEBUG 如果DEBUG 这个为真值 在#if 和#else 之间就要被预处理 #else 否则 #else 和#endif 要被预处理 #endif #if DEBUG 预处理1 #elif 条件2 预处理2 #else 预处理3 #endif // 一般出现在头文件用于保证#ifndef 和#endif 之间的预处理在a.out 只会预处理一次 如果__ADD_H_ 没有被定义过则定义这个宏预处理语句就会被执行。 如果__ADD_H_ 被定义过则#ifndef 和#endif 之间的就不会被预处理。 #ifndef __ADD_H_ #define __ADD_H_ 预处理 #endif 如果 这个宏被定义过__ADD_H_ 则预处理 会被执行。 一般用于代码中的一些选配功能。 #ifdef __ADD_H_ 预处理 #endif