“include”相信大家不会陌生,在我们写代码时,开头总会来一句“include XXX”。include是干嘛用的,很多教材都提到了,因此这里不会再详细解释了,大概意思就是将代码文件需要用到的函数声明、常量等包含到代码文件中。include不是C语言的关键字,而是属于一种预编译的指令,那么预编译又是个什么东东,这也是本文要详细阐述的内容。为了更好地阐述预编译的概念,我们先来看一段代码。有一个头文件,叫“MyCode.h”,内容如下:

MyCode.h文件内容:

int function(int a);



int function(int a)

{

    return a;

}

在MyCode.h文件中,我们声明了一个函数function,它带有一个整型的形参,返回值也是一个整型值,并且实现了这个函数。我们再写一个代码文件,叫“MyCode.c”,内容如下:

MyCode.c文件内容:

#include <stdio.h>

#include "MyCode.h"



int main()

{

    int a = 1;

    int b = 0;

    b = function(a);

    printf("在main函数中,b的值是%d\n", b);

    return 0;

}

在MyCode.c中,我们使用include包含了MyCode.h头文件,并且调用了function函数。在Visual C++ 6.0上编译,结果如下:


在VC编译之前,会有一个预编译的过程,即#include "MyCode.h"这一语句会将MyCode.h中的内容插入到相应的位置,那么预编译之后,MyCode.c如下:

...........

int function(int a);



int function(int a)

{

    return a;

}



int main()

{

    int a = 1;

    int b = 0;

    b = function(a);

    printf("在main函数中,b的值是%d\n", b);

    return 0;

}



预编译完了后,VC会继续编译main函数代码。说到这里,也许你还没看出预编译的用处,别急,我们现在修改下MyCode.c中的main函数体,在调用function时,参数是a+1,如下:

#include <stdio.h>

#include "MyCode.h"



int main()

{

    int a = 1;

    int b = 0;

    b = function(a + 1);

    printf("修改了main函数后,b的值是%d\n", b);

    return 0;

}



我们再来编译,结果如下:


这次编译中,由于MyCode.h没有做任何修改,而且之前也已经编译过一次,因此,MyCode.h本次不会再次编译。但是main函数中做了修改,因此,main函数部分会再次编译, 这就省去了MyCode.h的编译时间。试想,如果MyCode.h中有很多的函数声明,很多的函数实现,很多的变量、常量定义,很多的宏,MyCode.c中也包含了很多的头文件,那么,只要预编译一次这些头文件,以后不管怎么修改main函数,再次编译时,是不是能够省去很多的时间?这就是预编译的好处。当然,如果头文件也被修改了,那么头文件还是要重新编译的。

       说到这里,有人可能发现了,代码中有#include <stdio.h>和#include "MyCode.h",头文件一个用<>包含,一个用“”包含,两者有什么区别呢?

       对于使用<> 来包含头文件的方式,编译器会去系统目录中寻找头文件,而这个系统目录的位置,可以由你手动配置,也可以由编译器默认。比如,在VC中的配置方式如下:


这里指明了头文件在“D:\softwares\Microsoft Visual Studio\VC98”位置,这是VC安装时默认指定的。而“D:\CCode\MySQL\mysql-5.6.24-win32\include”是我安装MySql时,我自己配置的。如果编译器在上述目录中都找不到头文件stdio.h的话,就会报错!

       对于使用“”来包含头文件的方式,编译器会去当前编译的代码文件路径下找。比如,MyCode.c所在目录是“D:\CCode\Test”,则编译器会去“D:\CCode\Test”寻找MyCode.h,如果找不到,就会去上述系统目录中找,如果还找不到,就会报错!

聊聊C语言的预编译指令include的更多相关文章

  1. iOS中的预编译指令的初步探究

    目录 文件包含 #include #include_next #import 宏定义 #define #undef 条件编译 #if #else #endif #if define #ifdef #i ...

  2. c语言中条件编译相关的预编译指令

    一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...

  3. C语言的预编译,程序员必须懂的知识!【预编译指令】【预编译过程】

    由“源代码”到“可执行文件”的过程包括四个步骤:预编译.编译.汇编.链接.所以,首先就应该清楚的首要问题就是:预编译只是对程序的文本起作用,换句话说就是,预编译阶段仅仅对源代码的单词进行变换,而不是对 ...

  4. C/C++中的预编译指令

    工作中遇到的: 一个头文件中的: #pragma warning(disable:4996)#pragma warning(disable:4244)#pragma warning(disable:4 ...

  5. c/c++中的预编译指令总结

    预处理指令提供按条件跳过源文件中的节.报告错误和警告条件,以及描绘源代码的不同区域的能力.使用术语“预处理指令”只是为了与 C 和 C++ 编程语言保持一致.在 C# 中没有单独的预处理步骤:预处理指 ...

  6. C:预编译指令

    预编译 关于编译 参考 关于宏定义 参考 预编译又称为预处理,是做些代码文本的替换工作处理#开头的指令,比如拷贝#include包含的文件代码,#define宏定义的替换,条件编译等,就是为编译做的预 ...

  7. C语言的预编译

    由"源代码"到"可执行文件"的过程包括四个步骤:预编译.编译.汇编.链接.所以,首先就应该清楚的首要问题就是:预编译只是对程序的文本起作用,换句话说就是,预编译 ...

  8. C++ 内置宏定义 与 预编译指令

    内置宏和预编译指令, 在代码调试.单元测试.跨平台代码中经常会用到.这里记录一下. 1. 内置宏 (文件名,当前行号,当前日期,当前时间,当前执行方法名) __FILE____LINE____DATE ...

  9. Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma checksum(C# 参考)

    ylbtech-Docs-.NET-C#-指南-语言参考-预处理器指令:#pragma checksum(C# 参考) 1.返回顶部 1. #pragma checksum(C# 参考) 2015/0 ...

随机推荐

  1. C#高性能大容量SOCKET并发(零):代码结构说明

    原文:C#高性能大容量SOCKET并发(零):代码结构说明 C#版完成端口具有以下特点: 连接在线管理(提供在线连接维护,连接会话管理,数据接收,连接断开等相关事件跟踪): 发送数据智能合并(组件会根 ...

  2. C++中代理类和句柄类

    指针是 C 与其他语言区别的重要特征之一,在 C++ 中,指针也被广泛运用,我们通过指针实现多态.然而,众所周知,指针的使用必须小心,否则很容易造成内存泄漏 Memory Leak.当我们有几个指针指 ...

  3. 什么是T1与E1线路

    Leased Line 租用线路 租用线路是电信公司为某一机构建造的永久性通信电路.租用线路旁路了本地交换电信局(LEC)上的交换设备,所以在每次数据传输之前无需起始阶段,它们总是连通的.如果线路是长 ...

  4. kubernetes之使用http rest api访问集群

    系列目录 在Kubernetes集群中,API Server是集群管理API的入口,由运行在Master节点上的一个名为kube-apiserver的进程提供的服务. 用户进入API可以通过kubec ...

  5. 多进程界面开发-Qt试玩儿

    目录 一.概述 二.效果展示 三.使用方法 1.启动外部进程 2.创建Qt窗口 3.加入到主进程布局 四.嵌入NotePad 五.调用Ping命令 六.嵌入其他QWidget窗体 七.相关文章 一.概 ...

  6. RocketMQ(2)---Docker集群部署RocketMQ

    RocketMQ(2)-Docker集群部署RocketMQ =前言= 1.因为自己只买了一台阿里云服务器,所以RocketMQ集群都部署在单台服务器上只是端口不同,如果实际开发,可以分别部署在多台服 ...

  7. linux下安装Nginx1.16.0

    因为最近在倒腾linux,想安装新版本的nginx,找了一圈教程没有找到对应的教程,在稍微倒腾了一会之后终于成功的安装了最新版. 服务器环境为centos,接下来是详细步骤: 安装必要依赖插件 yum ...

  8. linux 下 设置 MySQL8 表名大小写不敏感方法,解决设置后无法启动 MySQL 服务的问题

    在安装完成之后,初始化数据库之前,修改 my.cnf 打开mysql配置文件 vim /etc/my.cnf 在尾部追加一行 lower_case_table_names=1 并保存,然后再初始化数据 ...

  9. Mysql事务隔离级别和锁机制

    一.Spring支持四种事务隔离级别: 1.ISOLATION_READ_UNCOMMITTED(读未提交):这是事务最低的隔离级别,它充许令外一个事务可以看到这个事务未提交的数据. 2.ISOLAT ...

  10. Java中的反射(1)

    Reflection in Java 反射到底是什么呢,我被问到的时候其实也没办法很好的回答这个问题,翻一翻博客,然后逐条讲解.今天干脆就整合一下,免得以后还要去翻. 首先讲一下Java是如何在运行时 ...