IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> C++入门教程(十一、宏) -> 正文阅读

[C++知识库]C++入门教程(十一、宏)

前面教程汇总

第一讲

C++入门教程(一、初步了解)

第二讲

C++入门教程(二、基本数据类型)

第三讲

C++入门教程(三、数组、注释与函数)

第四讲

C++入门教程(四、运算符与表达式)

第五讲

C++入门教程(五、数组与字符串)

第六讲

C++入门教程(六、指针)

第七讲

C++入门教程(七、结构体)

第八讲

C++入门教程(八、枚举类型)

第九讲

C++入门教程(九、语句与控制流)

第十讲

C++入门教程(十、联合体)

什么是预处理?

编译一个C语言或C++程序的第一步骤就是预处理阶段,这一阶段就是宏发挥作用的阶段。C和C++的预处理器在源代码编译之前对其进行一些文本性质的操作,主要任务包括删除注释、插入被 #include 进来的文件内容、定义和替换由 #define 定义的符号以及确定代码部分内容是否根据条件编译( #if )来进行编译。“文本性质”的操作,就是指一段文本替换成另外一段文本,而不考虑其中任何的语义内容。宏仅仅是在C预处理阶段的一种文本替换工具,编译完之后对二进制代码不可见

宏定义

宏常量

很简单,格式是 #define Object number ,比如定义一个π的值:

#define PI 3.14

可以直接用:

#define PI 3.14
#include <iostream>
using namespace std;

int main()
{
	cout << "圆周率约等于" << PI << endl;
	return 0;
}

输出结果:

3.14

宏语句

我们还可以用宏定义一条或多条语句。例如:

#include <cstdio>
#define Print printf("hello world!")
using namespace std;

int main()
{
	Print;  //预处理时会被替换为 printf("hello world!");
	return 0;
}

宏函数

我们还可以用宏来定义函数。宏定义也可以带参数,例如:

#include <cstdio>
#define Print(str) printf("%s",str)
using namespace std;

int main()
{
	Print("这是一个只有一条语句的宏函数!");
    //预处理时会被替换为 printf("%s","这是一个只有一条语句的宏函数!")
	return 0;
}

#undef 指令

#undef 是用来撤销宏定义的,用法如下:

#define PI 3.141592654
...
// code
#undef PI
//下面开始 PI 就失效了

ifndef 指令

使用 ifndef 防止头文件被重复包含和编译。这是宏定义的一种,它可以根据是否已经定义了一个变量来进行分支选择,一般用于调试等等.实际上确切的说这应该是预处理功能中三种(宏定义,文件包含和条件编译)中的一种----条件编译。 C语言或C++在对程序进行编译时,会先根据预处理命令进行“预处理”。C语言和C++的编译系统包括预处理,编译和链接等部分。

#ifndef x //先测试x是否被宏定义过
#define x //如果没有宏定义下面就宏定义x并编译下面的语句
...
...
...
#endif //如果已经定义了则编译#endif后面的语句

条件指示符 #ifndef 检查预编译常量在前面是否已经被宏定义。如果在前面没有被宏定义,则条件指示符的值为真,于是从 #ifndef#endif 之间的所有语句都被包含进来进行编译处理。相反,如果#ifndef指示符的值为假,则它与 #endif 指示符之间的行将被忽略。条件指示符 #ifndef 的最主要目的是防止头文件的重复包含和编译。

千万不要忽略了头文件的中的 #ifndef ,这是一个很关键的东西。比如你有两个C(或C++)文件,这两个C(或C++)文件都 include 了同一个头文件。而编译时,这两个C(或C++)文件要一同编译成一个可运行文件,于是问题来了,大量的声明冲突。

所以还是把头文件的内容都放在 #ifndef#endif 中吧。不管你的头文件会不会被多个文件引用,你都要加上这个。一般格式是这样的:

#ifndef <标识>
#define <标识>
...
#endif

<标识> 在理论上来说可以是自由命名的,但每个头文件的这个“标识”都应该是唯一的。标识的命名规则一般是头文件名全大写,前后加下划线,并把文件名中的“.”也变成下划线,如(这里以C语言举例子,因为这一讲的内容同时适用于C和C++):stdio.h

#ifndef _STDIO_H_
#define _STDIO_H_
......
#endif
#ifndef xxx //如果没有定义xxx
#define xxx //定义xxx
#endif //结束如果

这个用法主要是在头文件中,主要是为了防止类重复的 include ,所以在类的头文件之前加上前面两个,用类名替代 xxx ,在最后加上最后一句。

宏定义相关作用符

换行符 \

我们定义宏语句或者宏函数时不可能总是一条语句呀,那要是有很多条语句时怎么办?都写在一行吗?这样显然代码就不美观,可读性不好。所以有多条语句时,我们就在每行末尾(除了最后一行)加上 \ ,代表换行的意思。
例如:

#include <cstdio>
#define Print   printf("这是第1条语句\n");\
 		    	printf("这是第2条语句\n");\
 		    	printf("这是第3条语句\n")
 		    	
#define Show(str1,str2,str3)\
{\
	printf("%s\n",str1);\
	printf("%s\n",str2);\
	printf("%s\n",str3);\	
}
using namespace std;

int main()
{
	Print;  //无参数宏函数
	Show("first","second","third"); //带参数宏函数
	return 0;
}

字符串化符 #

# 是“字符串化”的意思,将出现在宏定义中的 # 是把跟在后面的参数转换成一个字符串。
例如:

#include <cstdio>
#define Print(str)\
{\
	printf(#str"的值是%d",str);\	
}
using namespace std;

int main()
{
	int x=3,y=4;
	Print(x+y); //此处等价于printf("x+y""的值是%d",x+y);
	            //#str等价于"x+y",所以#str不需要再用双引号引起来 
	return 0;
}

片段连接符 ##

## 是一种分隔连接方式,它的作用是先分隔,然后进行强制连接。在普通的宏定义中,预处理器一般把空格解释成分段标志,对于每一段和前面比较,相同的就被替换。但是这样做的结果是,被替换段之间存在一些空格。如果我们不希望出现这些空格,就可以通过添加一些 ## 来替代空格。
例:

#include <cstdio>
#define Add(n,value)\
{\
	num##n+=value;\
}
using namespace std;

int main()
{
	int num1=1;
	int num2=10;
	Add(2,10); //等价于num2+=10; 这里把num和2连接成了num2 
	printf(" num1=%d\n num2=%d",num1,num2); 
	return 0;
}

关于宏的内容还有很多,需要大家慢慢摸索,这里我就不再过多的介绍了(因为我不是特别喜欢用宏,喜欢用普通的 const 常量和函数等,因为它会无视很多限制,所以在大型场合下人们都会说宏是一种危险的东西)。注意,这只是入门教程,目的是让人们熟悉C++(因为我写的内容里面有很多带有C语言味,比如我总是用 printf ,而且我也C语言写惯了,所以大家也应该会熟悉C语言),而不是精通C和C++。我也不是C和C++方面的专家(特别厉害的),所以想要深入学习,还是得请大咖(非常无奈)。但是我为了教大家C++投入了很多时间,所以如果能得到你们的赞,那就太好了。

本文完。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-08-06 10:25:04  更:2022-08-06 10:28:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年4日历 -2024/4/19 7:27:09-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码