`
lianxiangbus
  • 浏览: 529991 次
文章分类
社区版块
存档分类
最新评论

【笔记】C++预处理命令

 
阅读更多

预处理命令是提供给编译器使用的,在对代码进行编译之前,先对预处理命令进行操作:

主要包括:文件引入#include,新的引入头文件不再加".h";

宏定义#define

编译选择,如#ifdef ,#else,#endif等。

1.(预编译头机制)

VC.NET 默认情况下使用预编译头(/Yu),不明白的在加入新.h文件后编译时总出现fatal error C1010: 在查找预编译头指令时遇到意外的文件结尾的错误。解决方法是在include头文件的地方加上#include "stdafx.h",或者打项目属性,找到“C/C++”文件夹,单击“预编译头”属性页。修改“创建/使用预编译头”属性为“不使用预编译头”。

2.预定义标识符

为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但是他们都会处理下面的4种:

__FILE__ 正在编译的文件的名字
__LINE__ 正在编译的文件的行号
__DATE__ 编译时刻的日期字符串,例如: "25 Jan 2006"
__TIME__ 编译时刻的时间字符串,例如: "12:30:55"

例如:cout<<"The file is :"<<__FILE__"<<"! The lines is:"<<__LINE__<<endl;

3.C/C++头文件一览

C、传统 C++
#include <assert.h>    //设定插入点
#include <ctype.h>     //字符处理
#include <errno.h>     //定义错误码
#include <float.h>     //浮点数处理
#include <fstream.h>    //文件输入/输出
#include <iomanip.h>    //参数化输入/输出
#include <iostream.h>   //数据流输入/输出
#include <limits.h>    //定义各种数据类型最值常量
#include <locale.h>    //定义本地化函数
#include <math.h>     //定义数学函数
#include <stdio.h>     //定义输入/输出函数
#include <stdlib.h>    //定义杂项函数及内存分配函数
#include <string.h>    //字符串处理
#include <strstrea.h>   //基于数组的输入/输出
#include <time.h>     //定义关于时间的函数
#include <wchar.h>     //宽字符处理及输入/输出
#include <wctype.h>    //宽字符分类

标准 C++ (同上的不再注释)
#include <algorithm>    //STL 通用算法
#include <bitset>     //STL 位集容器
#include <cctype>
#include <cerrno>
#include <clocale>
#include <cmath>
#include <complex>     //复数类
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>      //STL 双端队列容器
#include <exception>    //异常处理类
#include <fstream>
#include <functional>   //STL 定义运算函数(代替运算符)
#include <limits>
#include <list>      //STL 线性列表容器
#include <map>       //STL 映射容器
#include <iomanip>
#include <ios>       //基本输入/输出支持
#include <iosfwd>     //输入/输出系统使用的前置声明
#include <iostream>
#include <istream>     //基本输入流
#include <ostream>     //基本输出流
#include <queue>      //STL 队列容器
#include <set>       //STL 集合容器
#include <sstream>     //基于字符串的流
#include <stack>      //STL 堆栈容器    
#include <stdexcept>    //标准异常类
#include <streambuf>    //底层输入/输出支持
#include <string>     //字符串类
#include <utility>     //STL 通用模板类
#include <vector>     //STL 动态数组容器
#include <cwchar>
#include <cwctype>

using namespace std;

C99 增加

#include <complex.h>   //复数处理
#include <fenv.h>    //浮点环境
#include <inttypes.h>  //整数格式转换
#include <stdbool.h>   //布尔环境
#include <stdint.h>   //整型环境
#include <tgmath.h>   //通用类型数学宏

4.编译控制指令

这些指令的主要目的是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。使用格式,如下:

1、如果identifier为一个定义了的符号,your code就会被编译,否则剔除。

#ifdef identifier
your code
#endif

2、如果identifier为一个未定义的符号,your code就会被编译,否则剔除。

#ifndef identifier
your code
#endif

3、如果expression非零,your code就会被编译,否则剔除。

#if expression
your code
#endif

4、如果identifier为一个定义了的符号,your code1就会被编译,否则your code2就会被编译。

#ifdef identifier
your code1
#else
your code2
#endif

5、如果epression1非零,就编译your code1,否则,如果expression2非零,就编译your code2,否则,就编译your code3。

#if expressin1
your code1
#elif expression2
your code2
#else
your 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。

注:预编译头机制

这里介绍VC6的预编译功能的使用,由于预编译详细使用比较的复杂,这里只介绍几个最重要的预编译指令: /Yu, /Yc,/Yx,/Fp。其它的详细资料可以参考:
MSDN -> 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 <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。在左边的树形视图里选择整个工程。

我们可以使用预编译头功能了。以下是注意事项:
1):如果使用了/Yu,就是 说使用了预编译,我们在每个.cpp文件的最开头,我强调一遍是最开头,包含你指定产生pch文件的.h文件(默认是stdafx.h)不然就会有问题。 如果你没有包含这个文件,就告诉你Unexpected file end. 如果你不是在最开头包含的,你自己试以下就知道了,绝对有很惊人的效果。
2) 如果你把pch文件不小心丢了,根据以上的分析,你只要让编译器生成一个pch文件就可以了。也就是说把 stdafx.cpp(即指定/Yc的那个cpp文件)重新编译一遍就可以了。当然你可以傻傻的 Rebuild all。简单一点就是选择那个cpp文件,按一下Ctrl + F7就可以了。


分享到:
评论

相关推荐

    c++基础笔记:预处理命令、命名空间、转义字符、输入输出、数据类型、算数运算符、类型转换等

    本篇文章是博主在学习c++基础时所做第一篇笔记,适用于有一定c++学习基础的同学,有些地方是按照自己的学习习惯所作,...c++基础笔记:预处理命令、命名空间、转义字符、输入输出、数据类型、算数运算符、类型转换等。

    南方科技大学计算机系C++程序设计.rar

    今天写写最近学习的C++课程笔记,南科大于仕琪老师的C++课程我是在闲暇时光花了两天时间看完的,(于教授是OpenCV中国论坛管理者,技术高超为人低调,之前也在深圳先进院工作过,也算是我的前辈了,需要好好向前辈...

    google C++ 风格指南 - 中文版

    Google C++ 风格指南 - 中文版 目录 译者前言 背景 1. 头文件 1.1. #define 保护 1.2. 头文件依赖 1.3. 内联函数 1.4. -inl.h文件 1.5. 函数参数的顺序 1.6. #include 的路径及顺序 译者 (YuleFox) 笔记 2...

    C++入门《C++ How To Program》NOTES

    《C++ How To Program》学习笔记 Introduction to C++ Programming C++的注释 单行注释是 //(两个斜杠) 多行注释是 /* */ 在任何一段代码开始之前都用注释表明代码的作用是一个很好的习惯 每个C++语句都必须以分号...

    基于PyQt5实现的邮件拦截系统、视频播放器、以及pyqt5的学习笔记.zip

    这就是为什么在使用信号与槽机制的类里,必须添加一个Q_OBJECT宏的原因,只有添加了这个宏,moc才能对类里的信号与槽的代码进行预处理。 Qt Core模块是Qt类库的核心,所有其他模块都依赖于此模块,如果使用qmake来...

    c++基础教程,简洁扼要

    适合新手的教程,我自己也在学,以下是部分学习笔记 69 函数指针 70 动态内存分配 Dynamic memory pointer = new type pointer = new type [elements] 第一个表达式用来给一个单元素的数据类型分配内存。第二个...

    基于神经网络的人脸识别系统

    1、图像采集预处理模块 采用 opencv控制笔记本摄像头进行图像的采集,提取有待识别的人脸图像特征,即特征提取和选择,与现有的数据库中的人脸图像进行匹配和识别,在特征提取之前首先经过预处理,根据人脸定位结果...

    pytorch 图像预处理之减去均值,除以方差的实例

    如下所示: #coding=gbk ''' GPU上面的环境变化太复杂,这里我直接给出在笔记本CPU上面的运行时间结果 由于方式3需要将tensor转换到GPU上面,这一过程很消耗时间,大概需要十秒,故而果断抛弃这样的做法 ...

    基于Opencv框架和MFC相结合的小程序,操作笔记本电脑摄像头,完成拍照摄像图片渲染等功能.zip

    多语言支持:尽管OpenCV主要使用C++编写,但它提供了丰富的API绑定,支持包括C、Python、Java、MATLAB、JavaScript等多种编程语言,方便不同领域的开发者使用。 开源与免费:OpenCV遵循BSD开源许可证发布,用户...

    preprocessor_brainfuck:仅使用C预处理器的头脑笨拙的解释器

    预处理器Brainfuck解释器 该项目包含仅在C预处理器宏中编写的Brainfuck程序解释器。...预处理程序Brainfuck解释器效率非常低,在运行hello.bf时将使用大约16 GIGABYTES内存和15至20分钟的处理时间。

    leetcode316-LeetCode:力码

    笔记。 问题 算法 Python C++ 1. 二和 哈希 字典 unordered_map, 计数, 查找 2. 两个数相加 递归 没有任何 没有任何 3. 无重复字符的最长子串 哈希 字典 bitset,设置,重置 4. 两个有序数组的中位数 二分查找 // 和...

    leetcode分类-Marked_for_Deeplearning:Marked_for_Deeplearning

    我们的目标是提供具有标准格式的可用数据集(在下面的下载部分中进行了解释),以便它们可以直接用于实验中,而无需任何预处理工作量。 此 repo 中包含的数据集用于分类任务(主要是文本分类,情感数据集除外)。 令...

    tempo:蒙纳士时间序列分类库

    我们宁愿使用“变换”的概念,它相当于一个预处理步骤。 当前可用的转换是: 上下包络计算(与DTW和CDTW下限一起使用) 衍生物 因此,您可以轻松设置任何距离的派生版本。 请参阅下面的“”。 我们还提供。 笔记...

    hlsl2glslfork:基于ATI的HLSL2GLSL的HLSL到GLSL语言翻译器。 在Unity中使用

    继续开发,带有基于预处理程序代码。 我正在对其进行更改,以使其适用于用例。 可能完全不适合您! 对于相反的工具(从GLSL ES到HLSL转换器),请查看 。 请参阅维护不良的。笔记仅支持Direct3D 9样式的HLSL。 没有...

Global site tag (gtag.js) - Google Analytics