预处理指令是我们写在程序代码中的给预处理器(preprocessor)的 命令,而不是程序本身的语句。预处理器在我们编译一个C++程序时由编译器自动执行,它负责控制对程序代码的第一次验证和消化。

所有这些指令必须写在单独的一行中,它们不需要加结尾的分号;。

#define

在这个教程的开头我们已经提到了一种预处理指令: #define ,可以被用来生成宏定义常量(defined constantants 或 macros),它的形式是:

#define name value

它的作用是定义一个叫做name 的宏定义,然后每当在程序中遇到这个名字的时候,它就会被value代替,例如:

#define MAX_WIDTH 100
char str1[MAX_WIDTH];
char str2[MAX_WIDTH];

它定义了两个最多可以存储100个字符的字符串。

#define 也可以被用来定义宏函数:

#define getmax(a,b) a>b?a:b
int x=5, y;
y = getmax(x,2);

这段代码执行后y 的值为5 。

#undef

#undef 完成与 #define相反的工作,它取消对传入的参数的宏定义:

#define MAX_WIDTH 100
char str1[MAX_WIDTH];
#undef MAX_WIDTH
#define MAX_WIDTH 200
char str2[MAX_WIDTH];

#ifdef, #ifndef, #if, #endif, #else and #elif

这些指令可以使程序的一部分在某种条件下被忽略。

#ifdef 可以使一段程序只有在某个指定常量已经被定义了的情况下才被编译,无论被定义的值是什么。它的操作是:

#ifdef name
// code here
#endif

例如:

#ifdef MAX_WIDTH
char str[MAX_WIDTH];
#endif

在这个例子中,语句char str[MAX_WIDTH]; 只有在宏定义常量MAX_WIDTH 已经被定义的情况下才被编译器考虑,不管它的值是什么。如果它还没有被定义,这一行代码则不会被包括在程序中。

#ifndef 起相反的作用:在指令#ifndef 和 #endif 之间的代码只有在某个常量没有被定义的情况下才被编译,例如:

#ifndef MAX_WIDTH
#define MAX_WIDTH 100
#endif
char str[MAX_WIDTH];

这个例子中,如果当处理到这段代码的时候MAX_WIDTH 还没有被定义,则它会被定义为值100。而如果它已经被定义了,那么它会保持原值 (因为#define 语句这一行不会被执行) 。

指令#if, #else 和 #elif (elif = else if) 用来使得其后面所跟的程序部分只有在特定条件下才被编译。这些条件只能够是常量表达式,例如:

#if MAX_WIDTH>200
#undef MAX_WIDTH
#define MAX_WIDTH 200

#elsif MAX_WIDTH<50
#undef MAX_WIDTH
#define MAX_WIDTH 50

#else
#undef MAX_WIDTH
#define MAX_WIDTH 100
#endif

char str[MAX_WIDTH];

注意看这一连串的指令 #if, #elsif 和 #else 是怎样以 #endif 结尾的。

#line

当我们编译一段程序的时候,如果有错误发生,编译器会在错误前面显示出错文件的名称以及文件中的第几行发生的错误。

指令#line 可以使我们对这两点进行控制,也就是说当出错时显示文件中的行数以及我们希望显示的文件名。它的格式是:

#line number "filename"

这里number 是将会赋给下一行的新行数。它后面的行数从这一点逐个递增。

filename 是一个可选参数,用来替换自此行以后出错时显示的文件名,直到有另外一个#line指令替换它或直到文件的末尾。例如:

#line 1 "assigning variable"
int a?;

这段代码将会产生一个错误,显示为在文件"assigning variable", line 1 。

#error

这个指令将中断编译过程并返回一个参数中定义的出错信息,例如:

#ifndef __cplusplus
#error A C++ compiler is required
#endif

这个例子中如果 __cplusplus 没有被定义就会中断编译过程。

#include

这个指令我们已经见到很多次。当预处理器找到一个#include 指令时,它用指定文件的全部内容替换这条语句。声明包含一个文件有两种方式:

#include "file"
#include <file>

两种表达的唯一区别是编译器应该在什么路经下寻找指定的文件。第一种情况下,文件名被写在双引号中,编译器首先在包含这条指令的文件所在的目录下进行寻找,如果找不到指定文件,编译器再到被配置的默认路径下(也就是标准头文件路径下)进行寻找。

如果文件名是在尖括号 <> 中,编译器会直接到默认标准头文件路径下寻找。

#pragma

这个指令是用来对编译器进行配置的,针对你所使用的平台和编译器而有所不同。要了解更多信息,请参考你的编译器手册。

如果你的编译器不支持某个#pragma的特定参数,这个参数会被忽略,不会产生出错。

预定义的宏名称 (Predefined macro names)

以下宏名称在任何时候都是定义好的:

macro value
__LINE__ 整数值,表示当前正在编译的行在源文件中的行数。
__FILE__ 字符串,表示被编译的源文件的文件名。
__DATE__ 一个格式为 "Mmm dd yyyy" 的字符串,存储编译开始的日期。
__TIME__ 一个格式为 "hh:mm:ss" 的字符串,存储编译开始的时间。
__cplusplus 整数值,所有C++编译器都定义了这个常量为某个值。如果这个编译器是完全遵守C++标准的,它的值应该等于或大于199711L,具体值取决于它遵守的是哪个版本的标准。

例如:

// 标准宏名称
#include <iostream>
using namespace std;int main()
{cout << "This is the line number " << __LINE__;cout << " of file " << __FILE__ << ".\n";cout << "Its compilation began " << __DATE__;cout << " at " << __TIME__ << ".\n";cout << "The compiler gives a "<<"__cplusplus value of " << __cplusplus;return 0;
}
This is the line number 7 of file /home/jay/stdmacronames.cpp.
Its compilation began Nov 1 2005 at 10:12:29.
The compiler gives a __cplusplus value of 1

C++ 高级篇(五)—— 预处理指令相关推荐

  1. c# 扩展方法奇思妙用高级篇五:ToString(string format) 扩展

    在.Net中,System.Object.ToString()是用得最多的方法之一,ToString()方法在Object类中被定义为virtual,Object类给了它一个默认实现: 1     p ...

  2. 谷粒商城-个人笔记(高级篇五)

    目录 十一.支付 1.内网穿透 1).简介 2).使用场景 3).内网穿透常用软件和安装 2.支付整合 1).支付宝加密原理 2).配置支付宝沙箱环境 3).订单支付与同步通知 4).订单列表页渲染完 ...

  3. PhotoShop算法实现高级篇--色彩特效(三十五)

    PhotoShop算法实现高级篇--色彩特效(三十五) kezunhai@gmail.com http://blog.csdn.net/kezunhai Photoshop中有很多色彩特效,本文介绍几 ...

  4. echarts(五)高级篇(多坐标轴、复杂多坐标轴)

    高级篇 多坐标轴 多坐标轴的常见应用就是一个图表有两个y 轴. /*基于准备好的dom,初始化echarts实例*/ const myChart = echarts.init(document.get ...

  5. Spark性能优化指南:高级篇

    前言 继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问 ...

  6. Spark性能优化指南——高级篇

    继基础篇讲解了每个Spark开发人员都必须熟知的开发调优与资源调优之后,本文作为<Spark性能优化指南>的高级篇,将深入分析数据倾斜调优与shuffle调优,以解决更加棘手的性能问题. ...

  7. 【转】【技术博客】Spark性能优化指南——高级篇

    http://mp.weixin.qq.com/s?__biz=MjM5NjQ5MTI5OA==&mid=2651745207&idx=1&sn=3d70d59cede236e ...

  8. 谷粒商城之高级篇知识补充

    谷粒商城高级篇之知识补充 前言 本篇主要是完成谷粒商城高级篇开发时,我们需要了解并学习一部分补充的知识,才能更好的完成商城业务. 以后我们将商城任务和额外知识分开来编写,方便商城业务的连贯性. 下面是 ...

  9. 谷粒商城-个人笔记(高级篇二)

    目录 二.商城业务-首页 1.整合thymeleaf渲染首页 1).在"gulimall-product"项目中导入前端代码: 2).渲染一级分类数据&&整合dev ...

最新文章

  1. Git学习教程(六)Git日志
  2. SAP SD基础知识之组织架构设计-Shipping Point篇
  3. 关于jetbrains系列产品2018.1.5以后的使用(crack)方法
  4. 启动elasticsearch命令_快速安装ElasticSearch
  5. 关于蓝牙服务UUID自定义简介
  6. 微电子科学与工程要学计算机吗,微电子科学与工程专业就业前景如何 有前途吗...
  7. Django获取request header信息
  8. JDK源码(14)-Error、Exception
  9. 十六、K8s安全管理与资源限制
  10. SQL 删除重复数据,重复数据只保留ID最小的行
  11. ofd 文件发票解析
  12. LabVIEW 2021 工具包
  13. 基于django的实验室网站管理平台设计与实现(二)
  14. 纯js油猴插件版GUI页面助手
  15. Unable to instantiate application 解决方法
  16. [BZOJ4200][NOI2015]小园丁与老司机
  17. 前端学习--Bable的使用步骤
  18. Spring Boot缓存实战 Redis
  19. 什么是AAC音频格式 AAC-LC 和 AAC-HE的区别是什么
  20. 前端基础_JavaScript

热门文章

  1. serv-u无法自动启动:无法开始服务器!服务器执行缺少
  2. [转]经典的C语言著作,“C语言四书五经”
  3. 数据挖掘流程_数据流挖掘
  4. 如何更好的掌握一个知识点_如何成为一个更好的讲故事的人3个关键点
  5. 房价预测 search Search 中对数据预处理的学习
  6. 如何使用Retrofit,OkHttp,Gson,Glide和Coroutines处理RESTful Web服务
  7. python 使用c模块_您可能没有使用(但应该使用)的很棒的Python模块
  8. css扩展语言_如何决定是否应该链接或扩展CSS类
  9. select ...as_一起使用.select .map和.reduce方法可充分利用Ruby
  10. 纯函数式编程语言_纯功能编程语言如何改变您的生活。