c/c++中的预编译指令总结
预处理指令提供按条件跳过源文件中的节、报告错误和警告条件,以及描绘源代码的不同区域的能力。使用术语“预处理指令”只是为了与 C 和 C++ 编程语言保持一致。在 C# 中没有单独的预处理步骤;预处理指令按词法分析阶段的一部分处理。
预处理器的主要作用就是把通过预处理的内建功能对一个资源进行等价替换,最常见的预处理有:文件包含,条件编译、布局控制和宏替换4种。
文件包含:#include 是一种最为常见的预处理,主要是做为文件的引用组合源程序正文。
条件编译:#if,#ifndef,#ifdef,#endif,#undef等也是比较常见的预处理,主要是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
布局控制:#progma,这也是我们应用预处理的一个重要方面,主要功能是为编译程序提供非常规的控制流信息。
宏替换:#define,这是最常见的用法,它可以定义符号常量、函数功能、重新命名、字符串的拼接等各种功能。
下面我们看一下常见的预处理指令:
● #define 宏定义
● #undef 未定义宏
● #include 文本包含
● #ifdef 如果宏被定义就进行编译
● #ifndef 如果宏未被定义就进行编译
● #endif 结束编译块的控制
● #if 表达式非零就对代码进行编译
● #else 作为其他预处理的剩余选项进行编译
● #elif 这是一种#else和#if的组合选项
● #line 改变当前的行数和文件名称
● #error 输出一个错误信息
● #pragma 为编译程序提供非常规的控制流信息
下面我们对这些预处理进行一一的说明,考虑到宏的重要性和繁琐性,我们把它放到最后讲。
文件包含指令:
这种预处理使用方式是最为常见的,平时我们编写程序都会用到,最常见的用法是:
● #include <iostream> //标准库头文件
● #include <iostream.h> //旧式的标准库头文件
● #include "IO.h" //用户自定义的头文件
● #include "../file.h" //UNIX下的父目录下的头文件
● #include "/usr/local/file.h" //UNIX下的完整路径
● #include "..\file.h" //Dos下的父目录下的头文件
● #include "\usr\local\file.h" //Dos下的完整路径
这里面有2个地方要注意:
1、我们用<iostream>还是<iostream.h>?
我们主张使用<iostream>,而不是<iostream.h>,为什么呢?我想你可能还记得我曾经给出过几点理由,这里我大致的说一下:首先,.h格式的头文件早在98年9月份就被标准委员会抛弃了,我们应该紧跟标准,以适合时代的发展。其次,iostream.h只支持窄字符集,iostream则支持窄/宽字符集。
还有,标准对iostream作了很多的改动,接口和实现都有了变化。最后,iostream组件全部放入namespace std中,防止了名字污染。[NextPage]
2、<io.h>和"io.h"的区别?
其实他们唯一的区别就是搜索路径不同:
对于#include <io.h> ,编译器从标准库路径开始搜索
对于#include "io.h" ,编译器从用户的工作路径开始搜索
编译控制指令:
这些指令的主要目的是进行编译时进行有选择的挑选,注释掉一些指定的代码,以达到版本控制、防止对文件重复包含的功能。
使用格式,如下:
如果identifier为一个定义了的符号,your code就会被编译,否则剔除
2、
如果identifier为一个未定义的符号,your code就会被编译,否则剔除
3、
如果expression非零,your code就会被编译,否则剔除
4、
如果identifier为一个定义了的符号,your code1就会被编译,否则yourcode2就会被编译
5、
如果epression1非零,就编译your code1,否则,如果expression2非零,就编译your code2,否则,就编译your code3
其他预编译指令
除了上面我们说的集中常用的编译指令,还有3种不太常见的编译指令:#line、#error、#pragma,我们接下来就简单的谈一下。
#line的语法如下:
例如:#line 30 a.h 其中,文件名a.h可以省略不写。
这条指令可以改变当前的行号和文件名,例如上面的这条预处理指令就可以改变当前的行号为30,文件名是a.h。初看起来似乎没有什么用,不过,他还是有点用的,那就是用在编译器的编写中,我们知道编译器对C++源码编译过程中会产生一些中间文件,通过这条指令,可以保证文件名是固定的,不会被这些中间文件代替,有利于进行分析。
例如:
这条指令主要是给出错误信息,上面的这个例子就是,如果没有在UNIX环境下,就会输出This software requires the UNIX OS.然后诱发编译器终止。所以总的来说,这条指令的目的就是在程序崩溃之前能够给出一定的信息。
#pragma是非统一的,他要依靠各个编译器生产者,例如,在SUN C++编译器中:
预定义标识符
为了处理一些有用的信息,预处理定义了一些预处理标识符,虽然各种编译器的预处理标识符不尽相同,但是他们都会处理下面的4种:
1、__FILE__ 正在编译的文件的名字
2、__LINE__ 正在编译的文件的行号
3、__DATE__ 编译时刻的日期字符串,例如: "25 Dec 2000"
4、__TIME__ 编译时刻的时间字符串,例如: "12:30:55"
例如:cout<<"The file is :"<<__FILE__"<<"! The lines is:"<<__LINE__<<endl;
预处理何去何从
如何取代#include预处理指令,我们在这里就不再一一讨论了。
C++并没有为#include提供替代形式,但是namespace提供了一种作用域机制,它能以某种方式支持组合,利用它可以改善#include的行为方式,但是我们还是无法取代#include。
#progma应该算是一个可有可无的预处理指令,按照C++之父Bjarne的话说,就是:"#progma被过分的经常的用于将语言语义的变形隐藏到编译系统里,或者被用于提供带有特殊语义和笨拙语法的语言扩充。”
对于#ifdef,我们仍然束手无策,就算是我们利用if语句和常量表达式,仍然不足以替代她,因为一个if语句的正文必须在语法上正确,满足类检查,即使他处在一个绝不会被执行的分支里面。
c/c++中的预编译指令总结的更多相关文章
- iOS中的预编译指令的初步探究
目录 文件包含 #include #include_next #import 宏定义 #define #undef 条件编译 #if #else #endif #if define #ifdef #i ...
- C/C++中的预编译指令
工作中遇到的: 一个头文件中的: #pragma warning(disable:4996)#pragma warning(disable:4244)#pragma warning(disable:4 ...
- C#中的预编译指令介绍
原文:C#中的预编译指令介绍 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量 ...
- Unity 中使用预编译指令区分平台
在实际项目开发过程中,我们经常会根据平台来写一些逻辑 #if UNITY_EDITOR #elif UNITY_IPHONE #elif UNITY_ANDROID #endif 使用预编译指令能很好 ...
- C#编写中使用预编译指令代替不停的注释
是不是经常调试某个模块的时候,要打开一堆Console或者Debug.Log,printf 不调试的时候,又关掉.如此繁复的倒腾实在是烦 可以使用预编译指令代替这种做法 #define 自定义字段 . ...
- C/C++中的预编译指令(转)
reference:https://blog.csdn.net/sunshinewave/article/details/51020421 程序的编译过程可以分为预处理.编译.汇编三部分,其中预处理是 ...
- C#中的预编译指令介绍[转]
原文链接 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量,但是它没有具体的值 ...
- c语言中条件编译相关的预编译指令
一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...
- C#预编译指令
近日工作涉及到于外部系统交互,对方提供接口:但是在双方系统未联调时,引用外部DLL,相关类实例化,提示异常错误(错误消息正常):后面操作无法进行,那如何写调试代码,即在调试时不运行某段代码,而在正式发 ...
随机推荐
- 关闭会声会影2018提示UEIP.dll找不到指定模块
最近有一些会声会影2018用户反映在关闭后弹出UEIP.dll错误,不知道该怎么办才好,针对这个问题,小编下面为大家介绍下解决方法. 原因分析 出现这个错误跟会声会影安装路径有中文字符是密切相关的,导 ...
- hashlib模块使用详情
python常用模块目录 一:hashlib简介 1.什么叫hash:hash是一种算法(不同的hash算法只是复杂度不一样)(3.x里代替了md5模块和sha模块,主要提供 SHA1, SHA224 ...
- TCP半开连接与半闭连接
半打开(Half-Open)连接和半关闭(Half-Close)连接.TCP是一个全双工(Full-Duplex)协议,因此这里的半连接"半"字就是相对于全双工的"全&q ...
- Java线上应用故障排查之一:高CPU占用 (转)
一个应用占用CPU很高,除了确实是计算密集型应用之外,通常原因都是出现了死循环. (友情提示:本博文章欢迎转载,但请注明出处:hankchen,http://www.blogjava.net/hank ...
- 6. B树
一.B 树是一种多叉平衡查找树 相较于二叉结构的红黑树,B 树是多叉结构,所以在元素数量非常多的情况下,B 树的高度不会像二叉树那么大,从而保证查询效率. 一棵含 n 个结点的 B 树的高度 h = ...
- 团队介绍 you i
我们团队一共四个人,我们足够了解对方的优缺点,能够很好的进行交流沟通.对于一些问题也能有好的方法去解决,我做事情比较讲究高效和尽可能的完美,或者说要做到我自己觉得完美,才会停下来.对于一件事情,我有自 ...
- 404 Note Found -(课堂实战)- 项目UML设计(团队)
目录 团队信息 分工选择 课上分工 课下分工 ToDolist alpha版本要做的事情 燃尽图 UML 用例图 状态图 活动图 类图 部署图 实例图 对象图 时序图 包图 通信图 贡献分评定 课上贡 ...
- 注解实现IOC和DI
1.组件扫描 Spring3.0后为我们引入了组件自动扫描机制,它可以在类路径底下寻找标注了@Component.@Service.@Controller.@Repository注解的类,并把这些类纳 ...
- 【leetcode】62.63 Unique Paths
62. Unique Paths A robot is located at the top-left corner of a m x n grid (marked 'Start' in the di ...
- 敏捷开发之Scrum站立会议
Scrum是迭代式增量软件开发过程,通常用于敏捷开发.站立会议通常指Scrun方法中的每日站立会议.顾名思义,是每天以站姿的方式召开的会议.以下从功能及要点方面对其进行解释说明: 功能: 1. ...