C温故补缺(十二):预编译器与头文件

2023-02-14,,,,

预编译器

预编译器就是之前学的预编译指令的执行者

gcc -E test.c -o test.i

生成预编译文件就是翻译#指令

比如#include<stdio.h>就是把整个stdio.h头文件和项目文件连接

所用预编译指令

#define 定义宏
#include 包含一个源代码文件
#undef 取消已定义的宏
#ifdef 如果宏已经定义,则返回真
#ifndef 如果宏没有定义,则返回真
#if 如果给定条件为真,则编译下面代码
#else #if 的替代方案
#elif 如果前面的 #if 给定条件不为真,当前条件为真,则编译下面代码
#endif 结束一个 #if……#else 条件编译块
#error 当遇到标准错误时,输出错误消息
#pragma 使用标准化方法,向编译器发布特殊的命令到编译器中

error用来提示预编译的错误,当程序执行的#error时,输出信息,停止编译后续代码

如:

// #define a 10
#ifndef a
#error Const Variable a not defined
#endif

把第一行注释取消,

就预编译成功了

预编译宏

描述
DATE 当前日期,一个以 "MMM DD YYYY" 格式表示的字符常量。
TIME 当前时间,一个以 "HH:MM:SS" 格式表示的字符常量。
FILE 这会包含当前文件名,一个字符串常量。
LINE 这会包含当前行号,一个十进制常量。
STDC 当编译器以 ANSI 标准编译时,则定义为 1。

这些预编译的宏都是可以直接输出的

#include <stdio.h>

int main(){
printf("File :%s\n", __FILE__ );
printf("Date :%s\n", __DATE__ );
printf("Time :%s\n", __TIME__ );
printf("Line :%d\n", __LINE__ );
printf("ANSI :%d\n", __STDC__ );
}

宏运算符

①宏延续运算符

如果定义的宏太长,可以用\来多行表示

#define The_total_number_\
of_students 50

②字符串常量化运算符

使用#把宏参数转化成字符串常量

#include<stdio.h>
#define sayHello(name) printf("Hello " #name) int main(){
sayHello(Eve);
}

预编译,看预编译的结果:

③标记粘贴运算符

使用##把两个标记合成一个,一般用来组成变量

#include<stdio.h>
#define trans(n) printf("%d",message##n);
int main(){
int message313=0x0010;
trans(313);
}

查看预编译的结果:

④defined()运算符

defined用于判断宏是否定义,并返回真/假,一般和if连用,但ifdef和ifndef也能实现这样的效果

参数化的宏

CPP可以使用参数化的宏来模拟函数

如:

#define squre(x) ((x)*(x))
#include<stdio.h>
int main(){
printf("%d",squre(4));
}

头文件

建议把所有的常量、宏、系统全局变量和函数原型写在头文件中,在需要的时候随时引用这些头文件

引用头文件

引用系统头文件

#include<stdio.h>

< >括起来的表示系统环境中的头文件

" "括起来的表示用户头文件

#include"func.h"

预编译

test.c

#include"func.h"
int main(){
int arr[10];
}

func.h

#define Total 0
#define PI 3.142 int Best_item=0;
int getBest_item(int *);

预编译:

直接把头文件中的内容插入到.c代码中

只引用一次头文件

如果不小心引用了两次头文件,编译器就会处理两次,预编译文件中就会有两边头文件代码,可能会导致异常

#include"func.h"
int main(){
#include"func.h"
int arr[10];
}

预编译:

为了防止 这种情况,标准做法是将整个头文件放在条件语句中

#ifndef flag
#define flag
#define Total 0
#define PI 3.142 int Best_item=0;
int getBest_item(int *);
#endif

这样再编译就不会出现两遍了

这种结构就是C语言中的包装器#ifndef

C温故补缺(十二):预编译器与头文件的相关教程结束。

《C温故补缺(十二):预编译器与头文件.doc》

下载本文的Word格式文档,以方便收藏与打印。