预编译头文件,编译预处理以什么开头

  预编译头文件,编译预处理以什么开头

  所谓头文件预编译是指一些MFC标准头文件(如Windows。h和Afxwin。h)被预编译。以后编译项目时,不会编译这部分头文件,只会使用预编译结果。这样可以加快编译速度,节省时间。I .预编译头文件的说明

  所谓头文件预编译是指一些MFC标准头文件(如Windows。h和Afxwin。h)被预编译。以后编译项目时,不会编译这部分头文件,只会使用预编译结果。这样可以加快编译速度,节省时间。

  预编译头文件通过编译stdafx.cpp生成,并以项目名命名。由于预编译头文件的后缀是“pch”,所以编译后的结果文件是projectname.pch

  编译器通过头文件stdafx.h使用预编译头文件。头文件名称stdafx.h可以在项目的编译设置中指定。根据编译器,指令#include stdafx.h 之前的所有代码都是预编译的。它跳过指令#include stdafx。并用projectname.pch编译此指令后的所有代码

  所以所有CPP实现文件的第一条语句是:#include stdafx.h 。

  此外,每个实现文件CPP都包含以下语句:

  #ifdef _DEBUG

  #undef THIS_FILE

  static char THIS _ FILE[]=_ _ FILE _ _;

  #endif

  这意味着,如果生成了调试版本,则应该指明当前文件的名称。__FILE__是一个宏,由编译器在编译期间为其分配当前正在编译的文件的名称。

  VC。默认情况下,NET使用预编译头(/Yu)。但是,当添加新的。h文件,它总是出现致命错误C1010:在查找预编译头指令时遇到意外的文件尾错误。解决方法是将#include stdafx.h 添加到包含头文件中,或者键入项目属性,找到“C/C”文件夹,然后单击“预编译头”属性页。将“创建/使用预编译头”属性修改为“不使用预编译头”。

  二。C/C头文件列表

  C,传统C

  #include assert.h //设置插入点

  # include type . h//字符处理

  # include rrno . h//定义错误代码

  #include float.h //浮点数处理

  #include fstream.h //文件输入/输出

  #include iomanip.h //参数化输入/输出

  #include iostream.h //数据流输入/输出

  # include limits . h//定义各种数据类型的最大常数。

  #include locale.h //定义本地化函数

  #include math.h //定义数学函数

  # includes dio . h//定义输入/输出功能

  #include stdlib.h //定义杂项函数和内存分配函数。

  #include string.h //字符串处理

  # includes strrea . h//基于数组的输入/输出

  #include time.h //定义一个关于时间的函数

  #包含wchar.h //宽字符处理和输入/输出

  #include wctype.h //宽字符分类

  c标准(同上不再评论)

  #包含算法//STL通用算法

  #包含位集//STL位集容器

  #包括cctype

  #包括cerrno

  #包含时钟

  #包含cmath

  #包含复杂//复杂类

  #包括cstdio

  #包含cstdlib

  #包括cstring

  #包括ctime

  # include quee//STL队列容器

  #包含异常//异常处理类

  #包括fstream

  #include functional //STL定义算术函数(而不是运算符)

  #包括限额

  # include list//STL线性列表容器

  #包含映射//STL映射容器

  #包括iomanip

  #包括ios //基本输入/输出支持

  #包含输入/输出系统使用的iosfwd //预声明

  #包括iostream

  # inclusive stream//基本输入流

  # include stream//基本输出流

  #包含队列//STL队列容器

  # includset//STL集合容器

  #include sstream //基于字符串的流

  #包含堆栈//STL堆栈容器

  # includesstdexcept//标准异常类

  #include streambuf //底层输入/输出支持

  #包含字符串//字符串类

  #include实用程序//STL通用模板类

  #包含vector //STL动态数组容器

  #包含cwchar

  #包含cwctype

  使用命名空间std

  C99增加

  #include complex.h //复数处理

  #包含fenv.h //浮点环境

  #include inttypes.h //整数格式转换

  # includestdpool . h//布尔环境

  # includesdtdint . h//整数环境

  #include tgmath.h //常规类型数学宏

  三、预处理的由来

  在C语言的历史发展中,很多语言特性(尤其是语言的晦涩)都来源于C语言,预处理就是其中之一。从C语言继承C语言预处理器(C语言预处理器,Bjarne博士缩写为Cpp,不知道是不是C程序预处理器的缩写)。

  四。常见预处理功能

  预处理器的主要作用是用预处理的内置函数替换一个资源。最常见的预处理包括文件包含、条件编译、布局控制和宏替换。

  文件包含:#include是最常见的预处理,主要作为文件的引用来组合源程序文本。

  编译条件:# if、# ifndef、# ifdef、# endif、# undef等。也是常见的预处理,主要是在编译时选择性的选择并注释掉一些指定的代码,从而实现版本控制的功能,防止文件的重复包含。

  布局:#pragma,这也是我们应用程序预处理的一个重要方面。它的主要功能是为编译器提供非常规的控制流信息。

  宏替换:#define,这是最常见的用法。它可以定义各种函数,如符号常量、函数函数、重命名、字符串连接等。

  5.预处理说明

  预处理指令的格式如下:

  #指令令牌

  #符号应该是该行的第一个非空字符。一般我们放在开头。如果一行指令放不下,可以用“”控制,例如:

  #定义错误if(error) exit(1)

  等于

  #定义错误

  如果(错误)退出(1)

  让我们来看看常见的预处理指令:

  #定义宏定义

  #undef没有定义宏。

  #包含文本包含

  #ifdef编译已定义的宏

  如果宏未定义,则#ifndef编译

  #endif结束对编译块的控制。

  #如果表达式非零,则编译代码

  #else编译为其他预处理的剩余选项。

  #elif这是#else和#if的组合选项。//后面有例子

  #line改变当前的行数和文件名

  #error输出错误消息。

  #pragma为编译器提供了非常规的控制流信息。

  下面我们就来一一解释一下这些预处理。考虑到宏的重要性和复杂性,我们把它们放在了最后。

  不及物动词该文档包含说明

  这种预处理是最常见的使用方式,我们通常在编写程序时使用。最常见的用法是:

  #包含iostream //stdlib.h

  #include iostream.h //旧式stdlib.h

  #include IO.h //用户定义的头文件

  #包含./file . h //UNIX下父目录中的头文件

  # include /usr/local/file . h //UNIX下的完整路径

  # #包括.file . h //Dos/Dos下父目录中的头文件

  #在“usr local file . h”//dos下包含完整路径

  这里有两个地方需要注意:

  1.我们用iostream还是iostream.h?

  我们提倡用iostream代替iostream.h:

  首先,头文件在。h格式早在1998年9月就被标准委员会放弃了。我们应该紧跟标准,以适应时代的发展。其次,iostream.h只支持窄字符集,而iostream支持窄/宽字符集。况且标准对iostream做了很多改动,接口和实现都有变化。最后,将iostream组件全部放入命名空间std中,以防止名称污染。

  2.io.h和 io.h 的区别?

  其实两者唯一的区别就是搜索路径不同:对于#include io.h,编译器从标准库路径开始搜索;对于# includeIO.h ,编译器从用户的工作路径开始搜索。

  七。编译控制指令

  这些指令的主要目的是在编译时有选择地选择和注释掉一些指定的代码,从而实现版本控制的功能,防止文件的重复包含。使用如下格式:

  1.如果标识符是一个已定义的符号,你的代码将被编译,否则将被拒绝。

  #ifdef标识符

  你的代码

  #endif

  2.如果标识符是未定义的符号,您的代码将被编译,否则将被拒绝。

  #ifndef标识符

  你的代码

  #endif

  3.如果expression非零,你的代码会被编译,否则会被淘汰。

  #if表达式

  你的代码

  #endif

  4.如果标识符是一个已定义的符号,将编译代码1,否则将编译代码2。

  #ifdef标识符

  您的代码1

  #否则

  您的代码2

  #endif

  5.如果epression1不为零,则编译代码1;否则,如果expression2为非零,则编译code2否则,编译您的代码3。

  #如果表达式1

  您的代码1

  #elif表达式2

  您的代码2

  #否则

  您的代码3

  #enif

  其他预编译指令,除了上面提到的常用编译指令,还有三种不太常用的编译指令:#line、#error、#pragma。接下来就简单说一下他们吧。

  #line的语法如下:

  #行号文件名

  示例:#第30行a.h

  其中,文件名a.h可以省略。这个命令可以改变当前的行号和文件名。比如上面的预处理命令,可以把当前行号改成30,文件名是A.H,乍一看好像没什么用。不过还是有用的,就是在编译编译器的时候用。我们知道编译器在编译C源代码的过程中会产生一些中间文件。通过这个指令,可以保证文件名是固定的,不会被这些中间文件替换,有利于分析。

  #错误语法如下:

  #错误信息

  例如:

  #ifndef UNIX

  #错误该软件需要UNIX操作系统。

  #endif

  这个指令主要给出一个错误信息。在上面的例子中,如果它不在UNIX环境中,它会输出这个软件需要UNIX OS,然后诱导编译器终止。所以总之,这个指令的目的是在程序崩溃之前给出一些信息。

  #pragma是非统一的,它依赖于各种编译器生成器。例如,在VC中:

  #pragma注释(lib, dllTest.lib )

  导入库dllTest.lib.

  八。预定义标识符

  为了处理一些有用的信息,预处理定义了一些预处理标识符。虽然各种编译器的预处理标识符不同,但都处理以下四种:

  __FILE__正在编译的文件的名称。

  __LINE__正在编译的文件的行号。

  __DATE__编译时间的日期字符串,例如:“2006年1月25日”

  __TIME__编译时的时间字符串,例如:“12:30:55”

  示例:cout 文件是:“__FILE__ ”!这几行是:“_ _ LINE _ _ endl

  九。预处理何去何从?

  这里不讨论如何替换#include预处理指令。c没有提供#include的替代形式,但是namespace提供了一种范围机制,可以以某种方式支持组合。使用它可以改进#include的行为,但是我们仍然不能替换#include。

  #pragma应被视为可选的预处理指令。按照C之父Bjarne的说法,就是:“#pragma被过度地、经常地用于将语言的语义变形隐藏到编译系统中,或者提供具有特殊语义和笨拙语法的语言扩展。”

  对于#ifdef,我们还是无可奈何。即使我们使用if语句和常量表达式,仍然不足以取代它,因为if语句的主体必须语法正确,并且满足类检查,即使它在永远不会执行的分支中。

  X.预编译头文件的补充说明

  本文介绍了VC6的预编译功能的使用。因为预编译的详细用法比较复杂,这里只介绍几个最重要的预编译指令:/Yu,/Yc,/Yx,/Fp。其他详细信息请参见:

  MSDN - Visual Studio 6.0文档- Visual C 6.0文档- VC程序员指南-编译器和链接器-详细信息-创建预编译头文件

  预编译头的概念:

  所谓预编译头,就是将项目中的那部分代码进行预编译,放到一个文件中(通常扩展名为。pch)。这个文件称为预编译头文件。预编译的代码可以是任何C/C代码,甚至可以是inline的函数,但必须是稳定的,不会在项目开发过程中频繁更改。如果修改了这些代码,需要重新编译它们以生成预编译头文件。请注意,生成预编译头文件需要时间。同时,您应该注意,预编译头文件通常非常大,通常为6-7M。注意及时清理那些无用的预编译头文件。

  你可能会问:现在所有的编译器都有时间戳的功能。在编译整个项目时,编译器只会编译那些已经修改过的文件,而不会编译那些自上次编译以来没有修改过的文件。那么为什么要预编译头文件呢?下面是答案。我们知道编译器以文件为单位编译文件。修改文件后,它会重新编译整个文件。当然,东方和西方(。例如宏,预处理器)将不得不重新处理。VC的预编译头文件保存的就是这部分信息。以避免每次都必须重新处理这些头文件。

  根据上面的介绍,预编译头文件的作用当然是提高廉价速度。有了它,你就不用每次都编译不需要频繁修改的代码了。编译性能肯定会得到提高。

  要使用预编译头文件,我们必须指定一个头文件,这个头文件包含我们不经常更改的代码和其他头文件,然后我们用这个头文件生成一个预编译头文件(。pch文件)。想必大家都知道StdAfx.h这个文件很多人认为这是VC提供的一个“系统级”,是编译器自带的一个头文件。实际上,这个文件可以是任何名称。让我们检查由AppWizard生成的典型的基于MFC对话框的程序的预编译头文件。(因为AppWizard会为我们指定如何使用预编译头文件,所以默认为StdAfx.h,这是VC给的名字)。我们会发现这个头文件包含以下头文件:

  #包括afxwin.h //MFC核心和标准组件

  #包含afxext.h //MFC扩展

  #包含afxdisp.h //MFC自动化类

  #包含对Internet Explorer 4公共控件的afxdtctl.h //MFC支持

  #包含afxcmn.h

  这些是MFC中必须包含的头文件。当然,我们不太可能在我们的项目中修改这些头文件,所以它们是稳定的。

  那我们怎么指定它生成预编译头文件呢?我们知道头文件是不能编译的。所以我们还需要一个cpp文件来生成。pch文件。默认情况下,该文件是StdAfx.cpp。这个文件只有一个代码:# include "stdafx.h "。原因很自然,我们只是想让它编译——也就是说,我们只想要它的。cpp分机。我们可以使用/Yc compile开关指定StdAfx.cpp来生成一个. pch文件,使用/Fp compile开关来指定生成的pch文件的名称。打开项目-设置- C/C对话框。将类别指向预编译头。在左侧的树视图中选择整个项目。

  我们可以使用预编译头函数。以下是注意事项:

  1):如果使用/Yu,也就是说使用预编译。我们正处于每一个阶段的开端。cpp文件。我强调这是最开始的,它包含了。h文件(默认为stdafx.h ),您指定它来生成pch文件。不然就有问题了。如果你不包括这个文件,告诉你意外的文件结尾。如果一开始没有收录,自己试试下面的。它有绝对惊人的效果。

  2)如果不小心丢失了pch文件,根据上面的分析,可以只要求编译器生成一个pch文件。也就是说,重新编译stdafx.cpp(即指定/Yc的cpp文件)就足够了。你当然可以傻,重建一切。只需选择cpp文件,并按下Ctrl F7。

郑重声明:本文由网友发布,不代表盛行IT的观点,版权归原作者所有,仅为传播更多信息之目的,如有侵权请联系,我们将第一时间修改或删除,多谢。

留言与评论(共有 条评论)
   
验证码: