预处理指令提供按条件跳过源文件中的节、报告错误和警告条件,以及描绘源代码的不同区域的能力。使用术语“预处理指令”只是为了与 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++中的预编译指令总结的更多相关文章

  1. iOS中的预编译指令的初步探究

    目录 文件包含 #include #include_next #import 宏定义 #define #undef 条件编译 #if #else #endif #if define #ifdef #i ...

  2. C/C++中的预编译指令

    工作中遇到的: 一个头文件中的: #pragma warning(disable:4996)#pragma warning(disable:4244)#pragma warning(disable:4 ...

  3. C#中的预编译指令介绍

    原文:C#中的预编译指令介绍 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量 ...

  4. Unity 中使用预编译指令区分平台

    在实际项目开发过程中,我们经常会根据平台来写一些逻辑 #if UNITY_EDITOR #elif UNITY_IPHONE #elif UNITY_ANDROID #endif 使用预编译指令能很好 ...

  5. C#编写中使用预编译指令代替不停的注释

    是不是经常调试某个模块的时候,要打开一堆Console或者Debug.Log,printf 不调试的时候,又关掉.如此繁复的倒腾实在是烦 可以使用预编译指令代替这种做法 #define 自定义字段 . ...

  6. C/C++中的预编译指令(转)

    reference:https://blog.csdn.net/sunshinewave/article/details/51020421 程序的编译过程可以分为预处理.编译.汇编三部分,其中预处理是 ...

  7. C#中的预编译指令介绍[转]

    原文链接 1.#define和#undef 用法: #define DEBUG #undef DEBUG #define告诉编译器,我定义了一个DEBUG的一个符号,他类似一个变量,但是它没有具体的值 ...

  8. c语言中条件编译相关的预编译指令

    一. 内容概述 本文主要介绍c语言中条件编译相关的预编译指令,包括#define.#undef.#ifdef.#ifndef.#if.#elif.#else.#endif.defined. 二.条件编 ...

  9. C#预编译指令

    近日工作涉及到于外部系统交互,对方提供接口:但是在双方系统未联调时,引用外部DLL,相关类实例化,提示异常错误(错误消息正常):后面操作无法进行,那如何写调试代码,即在调试时不运行某段代码,而在正式发 ...

随机推荐

  1. 33.[LeetCode] Search in Rotated Sorted Array

    Suppose an array sorted in ascending order is rotated at some pivot unknown to you beforehand. (i.e. ...

  2. sshpass 指定密码远程 ssh 到服务器 或者 scp 发送文件到服务器

    在操作linux时,虽然可以对linux配置免秘钥登录,但是在配置免密码登录之前,是需要登录到其他节点主机的,这里提供一种类似ssh的方式,可以在命令后面加上相应的参数来设置你将要登录的远程主机的密码 ...

  3. php命名空间学习笔记。

    为什么要用命名空间? 在PHP中,命名空间用来解决在编写类库或应用程序时创建可重用的代码如类或函数时碰到的两类问题: 用户编写的代码 与  PHP内部的类/函数/常量或第三方类/函数/常量之间的名字冲 ...

  4. 智能客服 对话实现--python aiml包

    利用了python的aiml包进行应答 什么是AIML? AIML是Richard Wallace开发的. 他开发了一个叫A.L.I.C.E(Artificial Linguistics Intern ...

  5. 软件工程团队项目第一个Sprint评论

    (1)跑男:话说我没怎么听懂这个游戏是怎么玩的,可能是由于这是第一组,所以我没有反应过来把,界面设计的还可以,但是像设置,选关,帮助真心没看懂.有一种感觉就是,这个游戏是由一堆的漂亮的图片拼起来的,还 ...

  6. 【二分图匹配】Plug It In!

    http://codeforces.com/gym/101873 F 先对原图跑一遍匈牙利得到原始最大匹配,再遍历每个出度>1的点,考虑若新加入点,能否找到增广路,若可行则答案对应增加 代码: ...

  7. 静默调用ShellContextMenu 实现QQ文件共享

    我在CSDN提问题一直没人回复,一下午时间自己终于解决了问题 http://bbs.csdn.net/topics/391916381 现将过程录下 先说需求,我想实现的功能是 在程序中对文件调用百度 ...

  8. SpringBoot与Swagger2整合

    一.Swagger简介与优势 相信各位在公司写API文档数量应该不少,当然如果你还处在自己一个人开发前后台的年代,当我没说,如今为了前后台更好的对接,还为了以后交接方便,都有要求写API文档. Swa ...

  9. 6/2 sprint2 看板和燃尽图的更新

  10. 201621123037 《Java程序设计》第10周学习总结

    作业10-异常 标签(空格分隔): Java 1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结异常相关内容. 2. 书面作业 本次PTA作业题集异常 1. 常用异常 结合题集题目7 ...