c++预编译命令.doc_第1页
c++预编译命令.doc_第2页
c++预编译命令.doc_第3页
c++预编译命令.doc_第4页
c++预编译命令.doc_第5页
已阅读5页,还剩8页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

在所有的预处理指令中,#Pragma 指令可能是最复杂的了,它的作用是设定编译器的状态或者是指示编译器完成一些特定的动作。#pragma指令对每个编译器给出了一个方法,在保持与C和C+语言完全兼容的情况下,给出主机或操作系统专有的特征。依据定义,编译指示是机器或操作系统专有的,且对于每个编译器都是不同的。 其格式一般为: #Pragma Para 其中Para 为参数,下面来看一些常用的参数。 (1)message 参数。 Message 参数是我最喜欢的一个参数,它能够在编译信息输出窗口中输出相应的信息,这对于源代码信息的控制是非常重要的。其使用方法为: #Pragma message(“消息文本”) 当编译器遇到这条指令时就在编译输出窗口中将消息文本打印出来。 当我们在程序中定义了许多宏来控制源代码版本的时候,我们自己有可能都会忘记有没有正确的设置这些宏,此时我们可以用这条指令在编译的时候就进行检查。 假设我们希望判断自己有没有在源代码的什么地方定义了_X86这个宏可以用下面的方法 #ifdef _X86 #Pragma message(“_X86 macro activated!”) #endif 当我们定义了_X86这个宏以后,应用程序在编译时就会在编译输出窗口里显示“_ X86 macro activated!”。我们就不会因为不记得自己定义的一些特定的宏而抓耳挠腮了 。 (2)另一个使用得比较多的pragma参数是code_seg。格式如: #pragma code_seg( section-name,section-class ) 它能够设置程序中函数代码存放的代码段,当我们开发驱动程序的时候就会使用到它。 (3)#pragma once (比较常用) 只要在头文件的最开始加入这条指令就能够保证头文件被编译一次,这条指令实际上在VC6中就已经有了,但是考虑到兼容性并没有太多的使用它。 (4)#pragma hdrstop表示预编译头文件到此为止,后面的头文件不进行预编译。BCB可以预编译头文件以加快链接的速度,但如果所有头文件都进行预编译又可能占太多磁盘空间,所以使用这个选项排除一些头文件。 有时单元之间有依赖关系,比如单元A依赖单元B,所以单元B要先于单元A编译。你可以用#pragma startup指定编译优先级,如果使用了#pragma package(smart_init) ,BCB就会根据优先级的大小先后编译。 (5)#pragma resource *.dfm表示把*.dfm文件中的资源加入工程。*.dfm中包括窗体外观的定义。 (6)#pragma warning( disable : 4507 34; once : 4385; error : 164 ) 等价于: #pragma warning(disable:4507 34) / 不显示4507和34号警告信息 #pragma warning(once:4385) / 4385号警告信息仅报告一次 #pragma warning(error:164) / 把164号警告信息作为一个错误。 同时这个pragma warning 也支持如下格式: #pragma warning( push ,n ) #pragma warning( pop ) 这里n代表一个警告等级(1-4)。 #pragma warning( push )保存所有警告信息的现有的警告状态。 #pragma warning( push, n)保存所有警告信息的现有的警告状态,并且把全局警告 等级设定为n。 #pragma warning( pop )向栈中弹出最后一个警告信息,在入栈和出栈之间所作的 一切改动取消。例如: #pragma warning( push ) #pragma warning( disable : 4705 ) #pragma warning( disable : 4706 ) #pragma warning( disable : 4707 ) /. #pragma warning( pop ) 在这段代码的最后,重新保存所有的警告信息(包括4705,4706和4707)。 (7)pragma comment(.) 该指令将一个注释记录放入一个对象文件或可执行文件中。 常用的lib关键字,可以帮我们连入一个库文件。一、预编译头文件说明所谓头文件预编译,就是把一个工程(Project)中使用的一些MFC标准头文件(如Windows.H、Afxwin.H)预先编译,以后该工程编译时,不再编译这部分头文件,仅仅使用预编译的结果。这样可以加快编译速度,节省时间。预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include stdafx.h前的代码都是预编译的,它跳过#include stdafx. h指令,使用projectname.pch编译这条指令之后的所有代码。因此,所有的CPP实现文件第一条语句都是:#include stdafx.h。另外,每一个实现文件CPP都包含了如下语句:#ifdef _DEBUG#undef THIS_FILEstatic char THIS_FILE = _FILE_;#endif这是表示,如果生成调试版本,要指示当前文件的名称。_FILE_是一个宏,在编译器编译过程中给它赋值为当前正在编译的文件名称。VC.NET默认情况下使用预编译头(/Yu),不明白的在加入新.h文件后编译时总出现fatal error C1010: 在查找预编译头指令时遇到意外的文件结尾的错误。解决方法是在include头文件的地方加上#include stdafx.h,或者打项目属性,找到“C/C+”文件夹,单击“预编译头”属性页。修改“创建/使用预编译头”属性为“不使用预编译头”。二、C/C+头文件一览C、传统 C+#include /设定插入点#include /字符处理#include /定义错误码#include /浮点数处理#include /文件输入输出#include /参数化输入输出#include /数据流输入输出#include /定义各种数据类型最值常量#include /定义本地化函数#include /定义数学函数#include /定义输入输出函数#include /定义杂项函数及内存分配函数#include /字符串处理#include /基于数组的输入输出#include /定义关于时间的函数#include /宽字符处理及输入输出#include /宽字符分类标准 C+(同上的不再注释)#include /STL 通用算法#include /STL 位集容器#include #include #include #include #include /复数类#include #include #include #include #include /STL 双端队列容器#include /异常处理类#include #include /STL 定义运算函数(代替运算符)#include #include /STL 线性列表容器#include /STL 映射容器#include #include /基本输入输出支持#include /输入输出系统使用的前置声明#include #include /基本输入流#include /基本输出流#include /STL 队列容器#include /STL 集合容器#include /基于字符串的流#include /STL 堆栈容器#include /标准异常类#include /底层输入输出支持#include /字符串类#include /STL 通用模板类#include /STL 动态数组容器#include #include using namespace std;C99 增加#include /复数处理#include /浮点环境#include /整数格式转换#include /布尔环境#include /整型环境#include /通用类型数学宏三、预处理的由来在C+的历史发展中,有很多的语言特征(特别是语言的晦涩之处)来自于C语言,预处理就是其中的一个。C+从C语言那里把C语言预处理器继承过来(C语言预处理器,被Bjarne博士简称为Cpp,不知道是不是C Program Preprocessor的简称)。四、常见的预处理功能预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译、布局控制和宏替换4种。文件包含:#include 是一种最为常见的预处理,主要是做为文件的引用组合源程序正文。条件编译:#if,#ifndef,#ifdef,#endif,#undef等也是比较常见的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。布局控制:#pragma,这也是我们应用预处理的一个重要方面,主要功能是为编译程序提供非常规的控制流信息。宏替换:#define,这是最常见的用法,它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。五、预处理指令预处理指令的格式如下:#directive tokens#符号应该是这一行的第一个非空字符,一般我们把它放在起始位置。如果指令一行放不下,可以通过“”进行控制,例如:#define Error if(error) exit(1)等价于#define Error if(error) exit(1)下面我们看一下常见的预处理指令:#define 宏定义#undef 未定义宏#include 文本包含#ifdef 如果宏被定义就进行编译#ifndef 如果宏未被定义就进行编译#endif 结束编译块的控制#if 表达式非零就对代码进行编译#else 作为其他预处理的剩余选项进行编译#elif 这是一种#else和#if的组合选项 /后面有例子的#line 改变当前的行数和文件名称#error 输出一个错误信息#pragma 为编译程序提供非常规的控制流信息下面我们对这些预处理进行一一的说明,考虑到宏的重要性和繁琐性,我们把它放到最后讲。六、文件包含指令这种预处理使用方式是最为常见的,平时我们编写程序都会用到,最常见的用法是:#include /标准库头文件#include /旧式的标准库头文件#include IO.h /用户自定义的头文件#include ./file.h /UNIX下的父目录下的头文件#include /usr/local/file.h /UNIX下的完整路径#include .file.h /Dos下的父目录下的头文件#include usrlocalfile.h /Dos下的完整路径这里面有2个地方要注意:1、我们用还是我们主张使用,而不是:首先,.h格式的头文件早在98年9月份就被标准委员会抛弃了,我们应该紧跟标准,以适合时代的发展。其次,iostream.h只支持窄字符集,iostream则支持窄/宽字符集。还有,标准对iostream作了很多的改动,接口和实现都有了变化。最后,iostream组件全部放入namespace std中,防止了名字污染。2、和io.h的区别其实他们唯一的区别就是搜索路径不同:对于#include ,编译器从标准库路径开始搜索对于#include io.h ,编译器从用户的工作路径开始搜索。七、编译控制指令这些指令的主要目的是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。使用格式,如下:1、如果identifier为一个定义了的符号,your code就会被编译,否则剔除。#ifdef identifieryour code#endif2、如果identifier为一个未定义的符号,your code就会被编译,否则剔除。#ifndef identifieryour code#endif3、如果expression非零,your code就会被编译,否则剔除。#if expressionyour code#endif4、如果identifier为一个定义了的符号,your code1就会被编译,否则your code2就会被编译。#ifdef identifieryour code1#elseyour code2#endif5、如果epression1非零,就编译your code1,否则,如果expression2非零,就编译your code2,否则,就编译your code3。#if expressin1your code1#elif expression2your code2#elseyour code3#enif其他预编译指令除了上面我们说的集中常用的编译指令,还有3种不太常见的编译指令:#line、#error、#pragma,我们接下来就简单的谈一下。#line的语法如下:#line number filename例如:#line 30 a.h其中,文件名a.h可以省略不写。这条指令可以改变当前的行号和文件名,例如上面的这条预处理指令就可以改变当前的行号为30,文件名是a.h。初看起来似乎没有什么用,不过,他还是有点用的,那就是用在编译器的编写中,我们知道编译器对C+源码编译过程中会产生一些中间文件,通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析。#error语法如下:#error info例如:#ifndef UNIX#error This software requires the UNIX OS.#endif这条指令主要是给出错误信息,上面的这个例子就是,如果没有在UNIX环境下,就会输出This software requires the UNIX OS.然后诱发编译器终止。所以总的来说,这条指令的目的就是在程序崩溃之前能够给出一定的信息。#pragma是非统一的,他要依靠各个编译器生产者。例如VC+中:#pragma comment(lib,dllTest.lib)导入库dllTest.lib。八、预定义标识符为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但是他们都会处理下面的4种:_FILE_ 正在编译的文件的名字_LINE_ 正在编译的文件的行号_DATE_ 编译时刻的日期字符串,例如: 25 Jan 2006_TIME_ 编译时刻的时间字符串,例如: 12:30:55例如:coutThe file is :_FILE_! The lines is:_LINE_ Visual Studio 6.0 Document - Visual C+ 6.0 Document - VC+ Programmer Guider - Compiler and Linker - Details - Creating Precompiled Header files预编译头的概念:所谓的预编译头就是把一个工程中的那一部分代码,预先编译好放在一个文件里(通常是以.pch为扩展名的),这个文件就称为预编译头文件这些预先编译好的代码可以是任何的C/C+代码,甚至是inline的函数,但是必须是稳定的,在工程开发的过程中不会被经常改变。如果这些代码被修改,则需要重新编译生成预编译头文件。注意生成预编译头文件是很耗时间的。同时你得注意预编译头文件通常很大,通常有6-7M大。注意及时清理那些没有用的预编译头文件。也许你会问:现在的编译器都有Time stamp的功能,编译器在编译整个工程的时候,它只会编译那些经过修改的文件,而不会去编译那些从上次编译过,到现在没有被修改过的文件。那么为什么还要预编译头文件呢?答案在这里,我们知道编译器是以文件为单位编译的,一个文件经过修改后,会重新编译整个文件,当然在这个文件里包含的所有头文件中的东西(.eg Macro, Preprocessor )都要重新处理一遍。VC的预编译头文件保存的正是这部分信息。以避免每次都要重新处理这些头文件。根据上文介绍,预编译头文件的作用当然就是提高便宜速度了,有了它你没有必要每次都编译那些不需要经常改变的代码。编译性能当然就提高了。要使用预编译头,我们必须指定一个头文件,这个头文件包含我们不会经常改变的代码和其他的头文件,然后我们用这个头文件来生成一个预编译头文件(.pch文件)想必大家都知道 StdAfx.h这个文件。很多人都认为这是VC提供的一个“系统级别”的,编译器带的一个头文件。其实不是的,这个文件可以是任何名字的。我们来考察一个典型的由AppWizard生成的MFC Dialog Based程序的预编译头文件。(因为AppWizard会为我们指定好如何使用预编译头文件,默认的是StdAfx.h,这是VC起的名字)。我们会发现这个头文件里包含了以下的头文件:#include / MFC core and standard components#include / MFC extensions#include / MFC Automation classes#include / MFC support for Internet Explorer 4 Common Controls#include 这些正是使用MFC的必须包含的头文件,当然我们不太可能在我们的工程中修改这些头文件的,所以说他们是稳定的。那么我们如何指定它来生成预编译头文件。我们知道一个头文件是不能编译的。所以我们还需要一个cpp文件来生成.pch 文件。这个文件默认的就是StdAfx.cpp。在这个文件里只有一句代码就是:#include “Stdafx.h”。原因是理所当然的,我们仅仅是要它能够编译而已也就是说,要的只是它的.cpp的扩展名。我们可以用/Yc编译开关来指定StdAfx.cpp来生成一个.pch文件,通过/Fp编译开关来指定生成的pch文件的名字。打开project -Setting-C/C+ 对话框。把Category指向Precompiled Header。在左边的树形视图里选择整个工程,如下图:(Project -Settin

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论