45.宏
45.1 知识点
知识点回顾:什么是编译器
编译器是一种翻译程序,用于将源语言程序翻译为目标语言程序。编译器的主要任务是将人类可读的代码转换为计算机能执行的指令。
- 源语言程序:由某种程序设计语言编写的程序,例如 C++、C#、C、Java 等语言写的程序。
- 目标语言程序:机器代码或中间代码,是计算机可以识别和理解的内容。
什么是预处理指令
预处理器指令指导编译器在实际编译开始之前对信息进行预处理。预处理器指令都以 #
开始,并且它们不是语句,因此不以分号 ;
结束。我们经常用到的折叠代码块就是一种预处理器指令。
宏的基本概念
宏是一种预处理指令,主要作用是在编译之前替代源代码中的信息。它类似于一连串信息的别名(这些信息可以是数值、字符串、表达式等)。宏主要通过 #define
指令来创建,并且分为不带参数的宏和带参数的宏。
使用注意:
- 宏一般写在代码文件的最上方(
#include
下方)。 - 宏命名通常使用大写字母。
- 宏定义后不需要在行末加分号
;
。
- 宏一般写在代码文件的最上方(
宏的使用:不带参数的宏
#define PI 3.1415926
#define MAX_SIZE 100
#define COUT_HELLO cout << "Hello, World" << endl
#define INFO "信息"
基本语法
#define 宏名 用于替代的信息
主要作用
- 定义常量或简化代码中的重复部分。
cout << PI << endl; // 3.1415926
double default2 = PI * 3;
cout << default2 << endl; // 9.42478
COUT_HELLO; // Hello, World
string str = INFO;
cout << str << endl; // 信息
宏的使用:带参数的宏
#define MUL1(x, y) x * y
#define ADD1(x, y) x + y
#define MUL2(x, y) (x) * (y)
#define ADD2(x, y) (x + y)
基本语法
#define 宏名(参数) 参数使用表达式
主要作用
- 简化表达式、代码重用、条件表达式、避免函数调用开销。
注意事项
- 使用带参数的宏时要小心,因为它们不会进行类型检查,相对来说,内联函数更安全。
- 表达式中的括号使用要小心。
// 3 * 4 + 1 = 13
cout << MUL1(3, 4 + 1) << endl;//13
// 3 * 3 + 4 = 13
cout << 3 * ADD1(3, 4) << endl;//13
// 3 * 5 = 15
cout << MUL2(3, 4 + 1) << endl;//15
// 3 * 7 = 13
cout << 3 * ADD2(3, 4) << endl;//21
取消宏定义
#define UE4
#define UE5
#undef UE4
#undef UE5
#undef
用于取消宏定义,主要用于取消已定义的宏。
宏的使用:定义一个符号
基本语法
#define 符号
主要作用
定义一个符号,类似于一个没有值的变量,可以配合编译指令使用。
使用示例
使用宏来决定编译哪些代码,可以利用它来区分不同版本执行不同的代码等功能。
#ifdef UE4
cout << "UE4要执行的逻辑" << endl;
#elif defined(UE5)
cout << "UE5要执行的逻辑" << endl;
#else
cout << "其他版本执行的逻辑" << endl;
#endif
宏的优缺点
优点:
- 简化代码。
- 条件编译。
- 消除函数调用的开销。
- 灵活性(没有类型限制)。
- 便于全局修改。
缺点:
- 增加调试难度:宏在代码中展开,调试时可能难以追踪错误,错误信息可能不够清晰。
- 没有类型检查。
- 命名冲突:可能会与其他变量或函数名冲突。
- 缺乏作用域:宏没有作用域限制,它们在整个文件中有效。
- 可读性下降:过度使用宏,尤其是在复杂的宏定义中,可能会导致代码难以理解和维护。
总结
虽然宏在编程中很有用,但当可以使用常量、内联函数、枚举等功能替代宏时,应该尽量避免使用宏。
45.2 知识点代码
Lesson45_宏.cpp
#include <iostream>
#pragma region 知识点三 宏的使用 不带参数的宏
#define PI 3.1415926
#define MAX_SIZE 100
#define COUT_HELLO cout << "Hello,World" << endl
#define INFO "信息"
#pragma endregion
#pragma region 知识点四 宏的使用 带参数的宏
//要注意括号的使用
#define MUL1(x,y) x*y
#define ADD1(x,y) x+y
#define MUL2(x,y) (x)*(y)
#define ADD2(x,y) (x+y)
#pragma endregion
#pragma region 知识点五 取消宏定义
#define UE4
#define UE5
#undef UE4
#undef UE5
#pragma endregion
using namespace std;
int main()
{
std::cout << "宏\n";
#pragma region 知识点回顾 什么是编译器
//编译器是一种翻译程序
//它用于将 源语言程序 翻译为 目标语言程序
//编译器的主要任务是让人类可读的代码变成计算机能执行的指令
//源语言程序: 某种程序设计语言写成的,比如C++、C#、C、Java等语言写的程序
//目标语言程序: 机器代码或中间代码,让计算机等可以识别理解的内容
#pragma endregion
#pragma region 知识点一 什么是预处理指令
//预处理器指令 指导编译器 在实际编译开始之前对信息进行预处理
//预处理器指令 都是以#开始
//预处理器指令不是语句,所以它们不以分号;结束
//目前我们经常用到的 折叠代码块 就是预处理器指令
#pragma endregion
#pragma region 知识点二 宏的基本概念
//宏就是一种预处理指令
//它的主要作用就是在编译之前 替代源代码中的信息
//类似一连串信息的别名(信息可以是数值、字符串、表达式等等)
//宏主要通过
//#define指令来创建
//分为 不带参数的宏 和 带参数的宏
//使用注意:
//1.一般写在代码文件的最上方(#include下方)
//2.宏命名一般全为大写
//3.不需要在行末加分号;
#pragma endregion
#pragma region 知识点三 宏的使用 不带参数的宏
//基本语法
//#define 宏名 用于替代的信息
//主要作用
//定义常量或简化代码的重复部分
cout << PI << endl;//3.1415926
double default2 = PI * 3;
cout << default2 << endl;//9.42478
COUT_HELLO;//Hello,World
string str = INFO;
cout << str << endl;//信息
#pragma endregion
#pragma region 知识点四 宏的使用 带参数的宏
//基本语法
//#define 宏名(参数) 参数使用表达式
//主要作用
//简化表达式、代码重用、条件表达式、避免函数调用开销
//注意事项
//1.使用带参数的宏时要小心,因为它们不会进行类型检查
// 相对来说,内联函数更安全
//2.表达式中括号的重要性
// 3 * 4 + 1 = 13
cout << MUL1(3, 4 + 1) << endl;//13
// 3 * 3 + 4 = 13
cout << 3 * ADD1(3, 4) << endl;//13
// 3 * 5 = 15
cout << MUL2(3, 4 + 1) << endl;//15
// 3 * 7 = 13
cout << 3 * ADD2(3, 4) << endl;//21
#pragma endregion
#pragma region 知识点五 取消宏定义
//undef 宏
//undef表示取消宏
//主要用在宏定义符号时使用
#pragma endregion
#pragma region 知识点六 宏的使用 定义一个符号
//基本语法
//#define 符号
//主要作用
//定义一个符号,类似一个没有值的变量
//可以配合编译指令
//#ifdef 宏
//#elif defined(宏)
//#else
//#endif
//使用
//用宏来决定编译哪些代码
//可以利用它来区分不同版本执行不同的代码等功能
#ifdef UE4
cout << "UE4要执行的逻辑" << endl;
#elif defined(UE5)
cout << "UE5要执行的逻辑" << endl;
#else
cout << "其他版本执行的逻辑" << endl;
#endif
#pragma endregion
#pragma region 知识点七 宏的优缺点
//优点:
//1.简化代码
//2.条件编译
//3.消除函数调用的开销
//4.灵活性(没有类型限制)
//5.便于全局修改
//等等
//缺点:
//1.增加调试难度
// 宏在代码中展开,调试时可能难以追踪错误,错误信息可能不够清晰
//2.没有类型检查
//3.命名冲突
// 可能会与其他变量或函数名冲突
//4.缺乏作用域
// 宏没有作用域限制,它们在整个文件中有效
//5.可读性下降
// 过度使用宏,尤其是在复杂的宏定义中,可能会导致代码难以理解和维护
//等等
//宏虽然看起来挺有用
//但是日后再使用时
//如果能够被常量、内联函数、枚举等等功能替代宏功能时
//就不要使用宏了
#pragma endregion
}
45.3 练习题
请实现一个宏用于判断一个数是否是偶数
#define IS_EVEN(n) ((n) % 2 == 0)
请实现一个宏用于判断两个数谁更大
#define MAX(a, b) ((a) > (b) ? (a) : (b))
请实现一个宏用于计算一个数的平方
#define SQUARE(x) ((x) * (x))
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com