C++ 预处理器

2023-10-27

         预处理器是一些指令,指示编译器在实际编译之前所需完成的预处理。所有的预处理器指令都是以井号(#)开头,只有空格字符可以出现在预处理指令之前。例如 #include 指令,这个宏用于把头文件包含到源文件中。C++ 还支持很多预处理指令,比如 #include、#define、#if、#else、#line 等。

#define

         #define 预处理指令用于创建符号常量,该符号常量通常称为。在C或C++中,“宏”分为有参数和无参数两种。

无参宏

         无参宏的宏名后不带参数。其定义的一般形式为:

#define 标识符 字符串

         “#” 表示这是一条预处理命令。“define”为宏定义命令。“标识符”为所定义的宏名。“字符串”可以是常数、表达式、格式串等。例如:

#define M 110

         在程序编译之前,所有的宏都会被替换为宏定义中的字符串,然后再进行编译。

         例如, 测试下面这段代码,查看预处理的结果。

#include <iostream>
using namespace std;
 
#define PI 3.14159
 
int main ()
{ 
    cout << "Value of PI :" << PI << endl; 
 
    return 0;
}

         假设源代码文件已经存在,并使用 -E 选项进行编译,把结果重定向到 test.p: 

         查看源文件所在目录下的 test.p 文件,将会看到它已经包含大量的信息,而且在文件底部的值被改为如下3.14159:

参数宏

         可以使用 #define 定义一个带有参数的宏,在宏定义中的参数称为形式参数,在宏调用中的参数称为实际参数。带参宏定义的一般形式为:

#define 宏名(形参表) 字符串

         在字符串中含有各个形参。

         对带参数的宏,在调用中,不仅要宏展开,而且要用实参去代换形参。例如宏定义:

#define M(y) ((y)*(y)+3*(y))    // 宏定义

k = M(5);                       // 宏调用 

/* 在宏调用时,用实参5去代替形参y,经预处理宏展开后的语句为 */
k = ((5)*(5)+3*(5));

         实例:

#include <iostream>
using namespace std;
 
#define MIN(a,b) (a<b ? a : b)
 
int main ()
{
   int i, j;
   i = 100;
   j = 30;
   cout <<"较小的值为:" << MIN(i, j) << endl;
 
   return 0;
}

条件编译

         有选择地对部分程序源代码进行编译,这个过程被称为条件编译。条件预处理器的结构与 if 选择结构很像。

         例如下面这段预处理器的代码:只在调试时进行编译,调试开关可以使用一个宏DEBUG来实现:

#ifdef DEBUG
   cerr <<"Variable x = " << x << endl;

#endif

        如果在指令: #ifdef DEBUG 之前已经定义了符号常量 DEBUG,则会对程序中的 cerr 语句进行编译。

        可以使用 #if 0 语句注释掉程序的一部分,如下所示:

#if 0
   // 不进行编译的代码

#endif

        实例:

#include<iostream>
#define DEBUG
#define MIN(a,b) (((a)<(b))? a:b)

using namespace std;

int main()
{
	int i,j;
	i = 60;
	j = 25;
	
#ifdef DEBUG
    cerr<<"Trace: Inside main function"<<endl;
#endif

#if 0
    //不进行编译的代码
	cout<<"我不会被编译!"<<endl;
#endif

    cout<<"The minimum is "<<MIN(i,j)<<endl;
	
#undef DEBUG //终止宏定义DEBUG
	
#ifdef DEBUG
    cerr<<"Trace: Coming out of main function."<<endl;
#endif
  	
    return 0;
}

         执行结果如下:

Trace: Inside main function.
The minimum is 25

         对于宏定义还要说明以下几点:

  • 宏定义是用宏名来表示一个字符串,在宏展开时又以该字符串取代宏名,这只是一种简单的代换,字符串中可以含任何字符,可以是常数,也可以是表达式,预处理程序对它不作任何检查。如有错误,只能在编译已被宏展开后的源程序时发现。
  • 宏定义不是说明或语句,在行末不必加分号,若加上分号,则连分号也一起置换。
  • 宏定义必须写在函数之外,其作用域为宏定义命令起到源程序结束。如要终止其作用域可使用#undef命令。

# 和 ## 运算符

         # 和 ## 预处理运算符在 C++ 和 ANSI/ISO C 中都是可用的。 

# 运算符

         # 运算符会把字符串令牌转换为用引号引起来的字符串。例如下面的宏定义:

#define MKSTR(x) #x

         宏定义参数中含有需要特殊含义字符如"或\时,它们前面会自动被加上转义字符 \。

         实例:

#include <iostream>
#define MKSTR(x) #x

using namespace std;
 
int main ()
{
    cout << MKSTR(HELLO C++) << endl;
 
    return 0;
}

         预处理器把 MKSTR(HELLO C++) 转换成了 "HELLO C++",即:

cout << "HELLO C++" << endl;

## 运算符

         ## 运算符用于连接两个令牌。下面是一个实例:

#define CONCAT(x, y)  x ## y

         当 CONCAT 出现在程序中时,它的参数会被连接起来,并用来取代宏。如下面实例所示:

#include <iostream>
#define concat(a, b) a ## b

using namespace std;
 
int main()
{
   int xy = 100;   
   cout << concat(x, y);

   return 0;
}

         预处理器把 concat(x, y) 转换成了 xy,执行结果如下:

100

预定义宏

         C++ 提供了下表所示的一些预定义宏:

描述
__LINE__ 这会在程序编译时包含当前行号。
__FILE__ 这会在程序编译时包含当前文件名。
__DATE__ 这会包含一个形式为 month/day/year 的字符串,它表示把源文件转换为目标代码的日期。
__TIME__ 这会包含一个形式为 hour:minute:second 的字符串,它表示程序被编译的时间。

         宏的实例:

#include <iostream>
using namespace std;
 
int main ()
{
    cout << "Value of __LINE__ : " << __LINE__ << endl;
    cout << "Value of __FILE__ : " << __FILE__ << endl;
    cout << "Value of __DATE__ : " << __DATE__ << endl;
    cout << "Value of __TIME__ : " << __TIME__ << endl;
 
    return 0;
}

         执行结果如下:

Value of __LINE__ : 6
Value of __FILE__ : hello.cpp
Value of __DATE__ : Sep  6 2016
Value of __TIME__ : 14:38:50

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C++ 预处理器 的相关文章

随机推荐

  • blender中的灯光和相机学习笔记

    目录 环境光 灯光属性 比如高反 编辑灯光基础 灯光基本属性 EV渲染器 点光 日光 面光 自发光 环境光 在渲染视图中 没有任何光时 物体只受环境光的影响 灯光属性 比如高反 在视图层属性中设置 灯光基础 1 四种灯光 点光 日光 聚光
  • 计算机视觉学习总结:基本的图像操作和处理(二)

    Numpy NumPy http www scipy org NumPy 是非常有名的 Python 科学计算工具包 其中 包含了大量有用的思想 比如数组对象 用来表示向量 矩阵 图像等 以及线性代数函数 1 图像数组表示 from PIL
  • 随想录(程序员的缺点)

    The original address of the document http blog csdn net feixiaoxing article details 7555315 声明 版权所有 欢迎转载 请勿用于商业用途 联系信箱 f
  • nvcc 编译并行程序时报错gcc: error trying to exec ‘cc1plus‘: execvp: 没有那个文件或目录

    一 nvcc 编译程序时报错 gcc error trying to exec cc1plus execvp 没有那个文件或目录 cc1plus 是gcc编译工具链中用到的一个程序 报错非常直白 就是说gcc在执行时找不到这个程序 二 问题
  • 北京航空航天计算机考研科目,2020考研北京航空航天大学计算机考研考试科目...

    2020考研 名校一直是考研学子的首选 北京航空航天大学作为全国名校 也是深受考研学子热衷追捧 那么下面启航小编就来介绍一下 2020考研 北京航空航天大学计算机考研科目 的相关内容 供考研学子参考 一起来了解一下吧 1 北京航空航天大学计
  • vue-admin 详细注释,必须手把手做项目系列之(二)

    文章将会自动保存至草稿 更新 麻雀虽小五脏俱全 项目地址 https github com whylisa vue admin step by step git 前言 这两天项目上线楼主要一大推的事要忙 要和产品撕逼 要和后台讨论一系列的问
  • selenium面试题

    今天有同学问到seleinum面试的时候会问到的问题 随便想了想 暂时纪录一下 欢迎大家在评论中提供更多问题 回复是我自己的答案 如果大家有什么好的看法 可以留言交流 去哪儿的面试题 selenium中如何判断元素是否存在 selenium
  • 【C++】 探索程序 详细解读程序在运行过程中都发生了什么

    目录 头文件 源代码 头文件重复包含 问题 解决方案 程序生成过程 预处理Preprocessi 编译Compilation 汇编Assembly 链接Linking 编译期 运行期 编译期确定 运行期确定 编译期错误 运行期错误 类和对象
  • 解决某些软件无法在parallels desktop虚拟机下运行

    步骤1 打开注册表 点开始菜单 点运行 输入regedit exe后回车 步骤2 找到HKEY LOCAL MACHINE HARDWARE DESCRIPTION System 步骤3 找到右边的VideoBiosVersion 双击打开
  • 【计算机视觉

    文章目录 一 Precision Recall 和 F1 score 二 IoU 三 mAP 四 AP 4 1 定义 4 2 分类 4 2 1 APs 4 2 2 APr 4 2 3 两者之间的区别 一 Precision Recall 和
  • Linux Shell 常用命令总结

    1 find find pathname options print exec ok 让我们来看看该命令的参数 pathname find 命令所查找的目录路径 例如用 来表示当前目录 用 来表示系统根目录 print find 命令将匹配
  • ipad编写html,iPad HTML Focus

    Sorry folks I guess I have to bring you a bad news So much questions for HOW DO I FOCUS ON AN INPUT FIELD ON IPAD USING
  • c51两个定时器中断冲突_单片机学习day11—中断系统(外部中断 & 定时器/计数器)...

    51单片机的中断系统 非常非常非常重要 一 中断的概念 CPU在处理某一事件A时 发生了另一事件B请求CPU迅速去处理 中断发生 CPU暂时中断当前的工作 转去处理事件B 中断响应和中断服务 待CPU将事件B处理完毕后 再回到原来事件A被中
  • 蓝桥杯 算法训练 乘积最大Python实现(动态规划)详细

    资源限制 时间限制 1 0s 内存限制 256 0MB 问题描述 今年是国际数学联盟确定的 2000 世界数学年 又恰逢我国著名数学家华罗庚先生诞辰90周年 在华罗庚先生的家乡江苏金坛 组织了一场别开生面的数学智力竞赛的活动 你的一个好朋友
  • WPF应用无法从任务栏恢复(唤起)

    背景 两个window 一个在前 小屏播放视频 一个在后 全屏播放视频 点击切换按钮 两个window中的内容对调 当点击任意window上面的缩小按钮的时候 将所有的window的 windowState 设置为 minimized 期望
  • 数据结构—快速掌握如何手动求解关键路径

    看到一道题 分析如何手动求解关键路径 文末有题目出处 如上图 红点表示状态 边表示活动及其所需要的时间 这是用箭线表示活动 节点表示事件的一种网络图绘制方法 也称为双代号网络图 AOA 下面我们将利用其它快捷方法求出关键路径 方法一 逆推法
  • 美国国家安全局(NSA)网络攻击主战武器“酸狐狸”

    近日 国家计算机病毒应急处理中心对美国家安全局 NSA 酸狐狸 漏洞攻击武器平台 FoxAcid 进行了技术分析 该漏洞攻击武器平台是美国国家安全局 NSA 特定入侵行动办公室 TAO 也被称为 接入技术行动处 对他国开展网络间谍行动的重要
  • 乐高编程学c语言吗,乐高编程和少儿编程的区别

    大家好 我是时间财富网智能客服时间君 上述问题将由我为大家进行解答 乐高编程和少儿编程的区别如下 1 乐高编程是以调用编程模块指令让机器动起来为目的 通常需要编程的模块是已经写好存储在模块里的 学员做的只是将模块以不同的方式拼接组合起来 2
  • DataGridView控件常用属性

    DataGridView控件常用属性 1 AllowUserToAddRow 去掉最后一行添加行的选项 2 RowHeadersVisble 去掉第一列包含行标题的列 3 AutoSizeColumnsMode 可见列的自动调整大小 4 S
  • C++ 预处理器

    预处理器是一些指令 指示编译器在实际编译之前所需完成的预处理 所有的预处理器指令都是以井号 开头 只有空格字符可以出现在预处理指令之前 例如 include 指令 这个宏用于把头文件包含到源文件中 C 还支持很多预处理指令 比如 inclu