8.2 文件包含和条件编译
预备知识:
一个项目可以通过编译、连接最终形成一个可执行文件。
每个源文件(.cpp),都会单独编译,编译成一个目标文件(.o,也可能是.obj,扩展名跟操作系统有关)。
系统把这些.o文件进行链接,最终形成一个可执行文件。
编译干了什么事?笼统的说:词法、语法分析,目标文件,.o/, .obj的生成,优化之类的。这个编译我们可以拆开来看它干了几个事,一般来讲他会
1.预处理:
2.编译:词法、语法分析,目标代码生成,优化,产生一些临时文件。
3.汇编:产生.o(.obj)目标文件。
预处理是干什么的?咱们在源程序.cpp中加入一些特殊的代码(特殊的命令),这些特殊代码有一些特殊的能力,提供一些特殊功能。
编译系统会先对这些特殊代码做处理,这个就叫“预处理”,处理结果再和源程序代码一起进行上边 的2.的编译,3.汇编这一系列操作。
C语言一般提供三种预处理功能:1.宏定义; 2.文件包含 3.条件编译。
这三种功能也是通过在程序代码中写代码来实现,只不过这些代码比较特殊,都是已 # 开头。
一.文件包含
将另外一个文件的内容包含到本文件中,我们通过#include命令来实现。
一般格式:
#include <文件名>
#include常用于#include 其他.h文件。 .h文件称为头文件,h(head)。
我们常常把宏定义,函数说明,甚至一些其他的#include命令,以及其他一些全局变量的外部声明等等放在头文件中。
说明:
1.很多公共修改都可以放在.h文件中,但是你一旦修改了这个.h文件,也就相当于修改了#include这个头文件的cpp文件,那么这些.cpp文件系统会对其重新编译。
2.一个#include 只能包含一个文件,如果要包含多个文件,那就要写多个#include;
3.文件包含是可以嵌套的。一个头文件中还可以#include其他头文件。#include本质上就是把另外一个文件中的内容,搬到本文件中来。
4.include包含文件,""包含和 <>包含。
区别:
#include <stdio.h> //<>是系统目录中找头文件。所以标准的stdio.h头文件就用<>
#include "stdio.h" //"" 的含义是在首先在当前目录查找,如果找不到,再到系统目录中查找。 “” 用于自己写的头文件,让系统优先使用当前目录中定义的头文件。
二.条件编译
条件编译的几种形式:
形式1:当标识符被定义过,则程序段1进行编译;
否则,则程序段2编译。 #else这段可以没有。
#ifdef 标识符
程序段1(一堆代码)
#else
程序段2
#endif
例子:
#define DEBUG 1
#ifdef DEBUG
printf("1234684981023");
#endif
形式2:当标识符没有被定义过,则程序段1进行编译;
否则,则程序段2编译。 #else这段可以没有。
#ifndef 标识符
程序段1(一堆代码)
#else
程序段2
#endif
例子:
#define RELEASE 2
#ifndef RELEASE
printf("487125713504");
#endif
形式3:当指定表达式为真(非0)时就编译程序段1,否则编译程序段2;
我们事先给定一定的条件,就可以使程序在不同条件下实现不同的功能。
#if 标识符
程序段1(一堆代码)
#else
程序段2
#endif
#if 标识符
程序段1(一堆代码)
#elif
程序段2
#else
程序段3
#endif
例子:
#define PI 3.1415926
#if PI
printf("PI is defined");
#else
printf("PI is not defined");
#endif
条件编译的好处:
1.条件编译可以减少生成的目标文件的长度
2.以后开发面临跨平台问题,为了增加程序的可移植性,增加程序的灵活性,我们就必须采用条件编译;
#if _WIN32
WaitForSingleObject()
//...windows
#elif __linux__
epoll()
#else
#endif