预处理指令
从指令出现的地方 到文件末尾有效 一般默认放到开头
指令结尾处不需要分号
\可以折行
#include 加载其他源码文件
支持路径的形式
顺序没有关系
#include <stdio.h> <> 一般是系统自带的
#include "file.h" "" 一般是用户定义的
#define 宏
定义
将指定的词换成另一个词
一般来说,应该首先使用函数,它的功能更强、更容易理解。宏有时候会产生意想不到的替换结果
可读性差
字符串替换或简单的操作时 性能会好很多
同一个宏不允许重复定义
宏的替换 不涉及数据类型
#define MAX 100
#define AAX MAX * MAX
#define SQUARE(X) X*X
int i = SQUARE(2)
int i = SQUARE(3+4)
#define SQUARE(X) ((X) * (X))
int i = SQUARE(3+4)
#define X(a, b, ...) (10*(a) + 20*(b)), __VA_ARGS__
X(5, 4, 3.14, "Hi!", 12)
#define STR(x) #x
printf("%s\n", STR(3.123)); 结果为 printf("%s\n","3.123")
#define MK_ID(n) i##n
int MK_ID(1) 结果为 int i1;
#undef 取消宏
定义
取消不存在的宏 不报错
不确定是否以前定义过,就可以先用#undef取消,然后再定义
使用
#undef MAX
预定义宏
没有一个一个试,直接从书中复制过来
__DATE__:编译日期,格式为“Mmm dd yyyy”的字符串(比如 Nov 23 2021)。
__TIME__:编译时间,格式为“hh:mm:ss”。
__FILE__:当前文件名。
__LINE__:当前行号。
__func__:当前正在执行的函数名。该预定义宏必须在函数作用域使用。
__STDC__:如果被设为1,表示当前编译器遵循 C 标准。
__STDC_HOSTED__:如果被设为1,表示当前编译器可以提供完整的标准库;否则被设为0(嵌入式系统的标准库常常是不完整的)。
__STDC_VERSION__:编译所使用的 C 语言版本,是一个格式为yyyymmL的长整数,C99 版本为“199901L”,C11 版本为“201112L”,C17 版本为“201710L”。
#if…#elif…#else…#endif
预处理器的条件判断,满足条件时,内部的行会被编译,否则就被编译器忽略
条件可以是 宏 表达式
用于DEBUG模式 或什么环境加载什么文件
#if 0
const double pi = 3.1415;
#endif
#ifdef…#else…#endif 判断某个宏是否定义过
通过这个宏,判断库文件是否被加载了防止多次加载相同文件
只是检查宏是否定义 不检查宏值是
#if define 宏
#elif define 宏2
#else
#endif
#ifndef…#endif 判断这个宏没有被定义过
防止重复加载
等同于 #if !define
#ifndef MYHEADER_H
#define MYHEADER_H
#include "myheader.h"
#endif
其他
#line num(100)
下一行的行号重置成数字 并从数字开始
#line 100 "newFilename"
不仅改行号 还改文件名
#error Not C11
抛出错误 并终止编译
#pragma
修改编译器属性
#pragma c9x on 让编译器以C99 标准进行编译