预处理命令
#include,叫做文件包含命令(以#号开头的命令称为预处理命令)
使用尖括号< >和双引号" “的区别在于头文件的搜索路径不同:
使用尖括号< >,编译器会到系统路径下查找头文件;而使用双引号” ",编译器首先在当前目录下查找头文件,如果没有找到,再到系统路径下查找
宏定义
#define 宏名 字符串
宏名是标识符的一种,命名规则和变量相同。字符串可以是数字、表达式、if 语句、函数等。
// 例子
#define N 200
#define M (n*2+n*n)
带参数的宏定义
#define 宏名(形参列表) 字符串
注意:对于带参宏定义不仅要在参数两侧加括号,还应该在整个字符串外加括号。
// 举例
#define sq(x) ((x)*(x))
注意:在宏定义中,有时还会用到#和##两个符号,它们能够对宏参数进行操作。
一个 # 用来将宏参数转换为字符串,也就是在宏参数的开头和末尾添加引号。
#include "stdio.h"
#define STR(s) #s
int main(){
// 如果宏定义的时候,没有加#,那么下面: STR("hello world"),必须加引号
printf("%s\n",STR(hello world));
return 0;
}
// 输出:
"hello world"
两个 ## 称为连接符,用来将宏参数或其他的串连接起来。
#include <stdio.h>
#define CON1(a, b) a##e##b
#define CON2(a, b) a##b##00
int main() {
printf("%f\n", CON1(8.5, 2)); // 相当于 8.5e2
printf("%d\n", CON2(12, 34)); // 相当于 123400
return 0;
}
// 运行结果:
850.000000
123400
条件编译
#include "stdio.h"
int main(){
#if _WIN32 // 如果在win系统内,则执行下一行代码
printf("hello, windows");
#elif __linux__ //如果在linux系统内,则执行下一行代码
printf("hello, linux");
#else // 如果都不是,则执行下面的代码
printf("hello, world");
#endif
return 0;
}
上面的代码可以根据不同情况编译不同代码、产生不同目标文件的机制,这种情况就是条件编译。条件编译是预处理程序的功能,不是编译器的功能。
#ifdef – 如果宏名已经定义过了,则执行代码A,否则执行代码B
#ifdef 宏名
代码A
#else
代码B
#endif
#ifndef – 如果宏名没有定义,则执行代码A,否则执行代码B
#ifndef 宏名
代码A
#else
代码B
#endif
注意:
#if 后面跟的是“整型常量表达式”,而 #ifdef 和 #ifndef 后面跟的只能是一个宏名,不能是其他的
防止程序编译
#error 指令用于在编译期间产生错误信息,并阻止程序的编译
#error 错误信息