`

VC 预编译头

阅读更多

预编译头的概念:
在很多程序中,每个源文件都存在一些相同的部分。比如要包括相同的一些头文件,而且这些头文件可能很长,例如window.h。如果用普通的方法编译这些源文件,对这些头文件在每个源文件中的出现都要重新编译,作了很多重复工作。如果能将这些头文件专门进行编译,并且把结果存储起来。然后在编译包含这些头文件的源文件时,使用上述结果替代头文件在源文件中的出现,就可以大大减少工作量。Microsoft Visual C++提供的“预编译头文件”机制就支持这一功能。


所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++代码--------甚至是inline的函数,但是必须是稳定的,在工程开发的过程中不会被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。注意生成预编译头文件是很耗时间的。同时你得注意预编译头文件通常很大,通常有6-7M大。注意及时清理那些没有用的预编译头文件。

也许你会问:现在的编译器都有Time stamp的功能,编译器在编译整个工程的时候,它只会编译那些经过修改的文件,而不会去编译那些从上次编译过,到现在没有被修改过的文件。那么为什么还要预编译头文件呢?答案在这里,我们知道编译器是以文件为单位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有头文件中的东西(.eg Macro, Preprocesser )都要重新处理一遍。VC的预编译头文件保存的正是这部分信息。以避免每次都要重新处理这些头文件。

预编译头的使用:

方法一:手动方法

要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)

想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个“系统级别”的,编译器带的一个头文件。其实不是的,这个文件可以是任何名字的。我们来考察一个典型的由AppWizard生成的MFC Dialog Based 程序的预编译头文件。(因为AppWizard会为我们指定好如何使用预编译头文件,默认的是StdAfx.h,这是VC起的名字)。我们会发现这个头文件里包含了以下的头文件:

#include <afxwin.h>      // MFC core and standard components

#include <afxext.h>      // MFC extensions

#include <afxdisp.h>    // MFC Automation classes

#include <afxdtctl.h>        // MFC support for Internet Explorer 4 Common Controls

#include <afxcmn.h>  

这些正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文件的,所以说他们是稳定的。

那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是:#include “Stdafx.h”。原因是理所当然的,我们仅仅是要它能够编译而已―――也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件,通过/Fp编译开关来指定生成的pch文件的名字。打开project ->Setting->C/C++ 对话框。把Category指向Precompiled Header。

在Project Options(右下角的那个白的地方)可以看到 /Fp “debug/PCH.pch”,这就是指定生成的.pch文件的名字,默认的通常是 <工程名>.pch(我的示例工程名就是PCH)。

这时原来的Project Option变成了 Source File Option(原来是工程,现在是一个文件,当然变了)。在这里我们可以看到 /Yc开关,/Yc的作用就是指定这个文件来创建一个Pch文件。/Yc后面的文件名是那个包含了稳定代码的头文件,一个工程里只能有一个文件的可以有YC开关。VC就根据这个选项把 StdAfx.cpp编译成一个Obj文件和一个PCH文件。

在这里,Precomplier 选择了 Use ………一项,头文件是我们指定创建PCH 文件的stdafx.h文件。事实上,这里是使用工程里的设置,/Yu”stdafx.h”。

这样,我们就设置好了预编译头文件。也就是说,我们可以使用预编译头功能了。以下是注意事项:

1):如果使用了/Yu,就是说使用了预编译,我们在每个.cpp文件的最开头,我强调一遍是最开头,包含 你指定产生pch文件的.h文件(默认是stdafx.h)不然就会有问题。如果你没有包含这个文件,就告诉你Unexpected file end. 如果你不是在最开头包含的,你自己试以下就知道了,绝对有很惊人的效果…..

2)如果你把pch文件不小心丢了,根据以上的分析,你只要让编译器生成一个pch文件就可以了。也就是说把 stdafx.cpp(即指定/Yc的那个cpp文件)从新编译一遍就可以了。当然你可以傻傻的 Rebuild all。简单一点就是选择那个cpp文件,按一下Ctrl + F7就可以了。

方法二:自动使用

很简单只要指定/YX就可以了。或者在上图中选择Automatic………就可以了。注意的事情是如果你指定了/Yc /Yu的话,/Yx是会被忽略的。前者的优先级别高一些.
下面从另一个角度再看一下:
假设每个源文件的相同部分都出现在文件的开始部分。这一假设是很现实的。那么相同部分的结尾如何定位呢?由两种方法,一是由程序员在源文件中用#pragma hdrstop标记;二是指定对某个头文件的包含指示符(#include directive)作为结束标志。这个头文件被称为through header file,在/Yc或者/Yu命令参数中指明。
在编译第一个源文件时,将从文件头到预编译部分结束处的编译结果存储到一个预编译头文件中,扩展名通常是pch。这个过程称为预编译头文件的生成。这一步工作需要指定/Yc参数。在对其他源文件进行编译时,使用这个预编译头文件,此时用/Yu参数。生成的预编译头文件的名字通过/Fp参数指定。
下面举一个例子。假设Project中共用的宏定义,常量定义,头文件引用都放在prechdr.h中。我编辑一个prechdr.cpp来#include “prechdr.h”。对prechdr.cpp编译时就可以生成包含prechdr.h中内容的预编译头文件:
cl /Ycprechdr.h /Fp.\Debug\prechdr.pch prechdr.cpp
这样,就创建了prechdr.pch。在编译其他源文件时,使用prechdr.pch:
cl /Yuprechdr.h /Fp.\Debug\prechdr.pch others.cpp
在IDE中,可以将Project Settings设置成/Yuprechdr.h /Fp.\Debug\prechdr.pch。然后将prechdr.cpp的C++ tab中Precompile类别设置成Use precompiled header,即在使用Project Settings的基础上增加了/Yc参数。当/Yc和/Yu共存时,只有/Yc起作用。IDE在build Project时会最先编译prechdr.cpp以创建预编译头文件供其他源文件使用。









分享到:
评论

相关推荐

    终于搞懂了,预编译头文件

    &lt;br&gt;预编译头的使用: &lt;br&gt;要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的 &lt;br&gt;代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件) &lt;br&gt;想必...

    Vc自动编译脚本文件生成

    在.net2003环境下,使用此脚本文件可以自动编译多个工程,不再需要打开.net环境,非常方便。

    MFC高速二维曲线控件示例程序,VC2017编译通过

    老版本的VC使用stdafx.h作为预编译头,VC2017使用pch.h作为预编译头,为了方便,干脆取消掉预编译头:属性-&gt;c/c++-&gt;预编译头-&gt;不使用预编译头。在程序中我用到了控件的曲线自适应功能,会根据数据自动的将曲线填满...

    解析VC中预编译头文件的深入分析

    为什么预编译头文件:预编译头的概念: 所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C++...

    每次vc编译时自动增加版本号

    vc每次编译时,自动递增版本号信息 自己再vs2005下试验过,没有问题 使用方法: 将modifyver.exe拷到系统目录下(例如windows下) 在vc的预生成事件中加上“modifyver.exe $(ProjectName).rc” 思路是修改rc文件,用...

    winXP VC2010编译的最新 curl 7.25.0(exe, dll, lib)

    libcurl配置 vc windows vs2008/2010 ... 解压 打开根目录下的curlxxx....2、加入预编译选项:项目-&gt;属性-&gt;c/c++ -&gt;预处理器-&gt;预处理器,把 ;BUILDING_LIBCURL;HTTP_ONLY复制进去(注意不要丢了";") 就可以静态编译了

    浅谈VC中预编译的头文件放那里的问题分析

    本篇文章是对VC中预编译的头文件放那里的问题进行了详细的分析介绍,需要的朋友参考下

    C++预编译技术详解(叹为观止)

    非常详细系统地阐述了C++的预编译技术 预编译命令,结合VC6.0编译器进行了讲解

    CPlusPlusXML.rar

    tinyxml 解析xml的例子,如果出现:vc编程中出现 fatal error C1010: 在查找预编译头时遇到意外的文件结尾。是否忘记了向源中添加“#include "stdafx.h"”?解决办法 菜单--〉项目--〉设置,出现“项目设置”对话框,...

    CFolderDialog VC++ mfc 获取“文件夹”的类

    1、在解决方案中右键,添加——》现有项,把FolderDialog.h和FolderDialog.cpp添加到...4、在“项目”-》属性-》配置属性-》C/C++——》预编译头——》创建/使用预编译头 中选择"不使用使用预编译头",否则编译会出错

    vc的stdafx文件和C1083、C1010错误

    介绍了产生C1083以及1010错误的一般原因,以及解决之道

    VS90SP1-KB976656-x86-VC2008.zip

    解决 VC2008 fatal error C1859:意外的预编译头错误,只需重新运行编译器就可能修复此问题

    winzlog用VS2010重新编译的

    2、包含以下预编译指令: #ifdef _DEBUG #ifndef _WIN64 #pragma comment(lib, "zlog_vc100x86.debug.lib") #else #pragma comment(lib, "zlog_vc100x64.debug.lib") #endif #else #ifndef _WIN64 #pragma comment...

    Visual C++代码整理工具(astyle)

    如果你是一名VC程序员,你是否被一个...如果采用其他工具对源文件进行代码整理,又需在VC之外重新打开源代码,整理结果不能直接在VC中查看编译。能不能在VC中集成一种工具,轻松点击VC按钮即可整理源码呢?回答是有。

    VC6工程升级VS2013遇到的问题.docx

    VC6工程升级VS2013遇到的问题.总结,包括一些编译链接时提示找不到预编译头, 以及在vc6.0中如何干净的删除类等建议和问题

    OpenCV 3.2+opencv_contrib3.2 CMake编译库install打包(64位 Debug版)

    VC++目录--&gt;包含目录,添加: (解压路径)\install\include (解压路径)\install\include\opencv (解压路径)\install\include\opencv2 VC++目录--&gt;库目录,添加: (解压路径)\install\x64\vc12\lib (解压路径)\...

    Linux中gdb查看core堆栈信息

    预编译头的使用: 要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的 代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件) 想必大家都知道 StdAfx.h这个文件。...

    VC dotNET特性演示软件.rar

    VC dotNET特性演示软件,Form1.cpp  这是主应用程序源文件。  包含显示窗体所需的代码。... 这些文件用于生成名为 Win32.pch 的预编译头(PCH)文件  以及名为 StdAfx.obj 的预编译类型文件。

Global site tag (gtag.js) - Google Analytics