Cpp知识点系列-宏定义

前言

一句话,宏定义就是全局替换和声明的一种方式!

我原本以为没必要详细了解,后来发现做错了题,纠结之后还是整理一下好了。

宏定义

掌握"宏"概念的关键是“”。一切以换为前提、做任何事情之前先要换!

不含参

#define PI 3.1415926

把程序中出现的PI全部换成3.1415926

#define endl '\n'

把程序中出现的endl全部换成字符'\n'

含参

例子1

#include<iostream>

#define endl '\n'
#define SR(x, y) x+y
using namespace std;

void sum1() {
    int a = 5, b = 4;
    a += 2 * SR1(a, b);
    cout << "sum1=" << a << endl;//结果是19
}

第一步,先换:语句替换后成为a+=2*a+b

第二步,替换变量,语句替换后成为5+=2*5+4

第三步,计算式子,先是右侧公式计算结果为14,此时为5+=14;最后赋值到变量上,结果是19

例子2

#include<iostream>
#define endl '\n'
#define SR(x, y) ((x)+(y))
using namespace std;

void sum2() {
    int a = 5, b = 4;
    a += 2 * SR2(a, b);
    cout << "sum2=" << a << endl;//结果是23
}

第一步,先换:语句替换后成为a+=2*((a)+(b))

第二步,替换变量,语句替换后成为5+=2*(5+4)

第三步,计算式子,先是右侧公式计算结果为18,此时为5+=18;最后赋值到变量上,结果是23

例子3

#define fun1(a) a

void f1() {
    cout << "f1=" << fun1(12 + 3)<< endl;//结果是数字15
}

#define fun2(a) "a"

void f2() {
    cout << "f2=" << fun2(12 + 3)<< endl;//结果是字符串a
}

请看清楚,定义的后面究竟是参数本身还是带着双引号的字符串!

含参循环

#include <iostream>

using namespace std;

// #define doit(m, n) for(int i=0;i<(n);++i){m+=i;}
#define doit(m,n) for(int i=0;i<(n);++i)\
{\
m+=i;\
}

int main() {
    int a = 5, b = 4;
    doit(a, b);
    cout << a;// 结果为11
    return 0;
}

宏定义也是可以分行的!!!

宏定义也是可以运行循环的!!!

宏定义也是能让人栽跟头的!!!

宏定义语法特点

###

  • 使用#把宏参数变为一个字符串

  • ##把两个宏参数贴合在一起

#include<iostream>

using namespace std;

#define endl '\n'
#define STR(s)     #s
#define CONS(a, b)  int(a##e##b)

int main() {
    cout << STR(vck)<< endl;       // 输出字符串"vck"
    cout << CONS(2, 3);  // 2e3 输出:2000
    return 0;
}
#undef CONS
#undef STR

其实照我现在的理解,有这种复杂需求的话还是写成函数更合适一些。

单纯为了炫技的话,当我没说……

更多详细应用还是参考原文博客吧,传送门在文末。

特点

  1. 宏定义末尾不加分号

  2. 宏定义写在函数的花括号外边,作用域为其后的程序,可以用#undef命令终止作用域

  3. 宏定义可以嵌套

  4. 字符串""中永远不包含宏

  5. 宏定义不分配内存,想要分配内存去使用变量吧。

  6. 预处理不做语法检查。因为预处理是在编译之前的处理,而编译工作的任务之一就是语法检查

  7. 宏定义不做计算,只作替换

  8. 宏的哑实结合不存在类型,也没有类型转换。

优点

使用宏可提高程序的通用性和易读性,减少不一致性,减少输入错误和便于修改。

例如:数组大小常用宏定义。

与函数的区别

    • 函数调用是在编译后程序运行时进行,并且分配内存。

    • 宏替换在编译前进行,不分配内存

    • 函数一般只有一个返回值,特殊情况下用pair也是一个对象,对象内两个值

    • 宏则可以设法得到多个值

  1. 宏展开会使源程序变长,函数调用不会

    • 函数调用占运行时间(分配内存、保留现场、值传递、返回值)

    • 宏展开不占运行时间,只占编译时间

感谢

源文件:

gitee:https://gitee.com/JunKuangKuang/KeenCPPTest-all/tree/main/basic/define

github.com:https://github.com/JunKuangKuang/KeenCPPTest-all/blob/main/basic/define

感谢现在的好奇,为了能成为更好的自己。

王珂的个人笔记

 

### 宏定义的全面介绍 #### 什么是宏? 在 C 和 C++ 中,宏是一种简单的代码替换机制,在源文件被编译之前由预处理器执行。它可以通过 `#define` 指令实现,通常用于简化重复代码、提高可读性和性能优化。 #### 宏的分类 1. **无参宏** 这是最基本的形式,用来替代一段固定的代码或数值。 ```c #define PI 3.1415926 ``` 2. **带参宏** 带有参数的宏可以接受输入并返回计算结果。 ```c #define SQUARE(x) ((x) * (x)) int result = SQUARE(5); // 结果为 25 ``` 需要注意的是,为了防止副作用,建议总是用括号包裹表达式的每一部分[^3]。 --- #### 宏的作用范围 宏的作用域是从其定义处到当前文件结束为止。如果希望在整个项目中使用某个宏,则可以在头文件中定义该宏,并通过 `#include` 将其引入各个模块。 ```c // common.h #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #include "common.h" int main() { int larger = MAX(10, 20); } ``` --- #### 条件编译中的宏 条件编译允许开发者根据特定条件决定哪些代码会被编译。常用的指令包括: - `#ifdef`: 如果某宏已定义则编译下面的内容; - `#ifndef`: 如果某宏未定义则编译下面的内容; - `#if`, `#elif`, `#else`: 支持复杂的逻辑判断。 示例: ```c #ifdef DEBUG_MODE printf("Debug mode is enabled.\n"); #endif ``` 还可以结合多个条件进行复杂控制: ```c #if defined(MY_TEST_VER) && (MY_TEST_VER >= 2) // 特定版本下的功能实现 #endif ``` 这种技术广泛应用于跨平台开发以及调试模式下启用特殊行为的情况[^1]。 --- #### 处理不同语言特性 由于 C 和 C++ 的函数命名规则存在差异——C 不支持重载而 C++ 支持——因此当需要混合两种语言编写时,需特别小心链接问题。解决办法之一就是利用外部声明块告知 C++ 编译器按照 C 的方式处理某些函数名称。 ```cpp #ifdef __cplusplus extern "C" { #endif void my_c_function(); #ifdef __cplusplus } /* extern "C" */ #endif ``` 这样做的目的是让这些函数能够被其他语言调用而不受名字修饰的影响[^2]。 --- #### 使用注意事项 尽管宏非常强大且灵活,但也容易引发潜在问题,比如难以追踪错误位置、缺乏类型安全等。因此现代编程实践中推荐优先考虑内联函数或其他高级抽象手段代替简单宏操作。 另外值得注意的一点是关于大小写约定:传统上程序员倾向于把所有的宏都命名为全大写字母形式以便快速识别它们并非普通变量或者函数;不过对于那些仅限局部使用的临时性小型辅助工具来说也可以采用小写或者其他风格书写[^3]。 --- ### 示例代码展示 以下是几个实际应用的例子来加深理解: 1. 计算绝对值: ```c #define ABS(x) (((x) < 0) ? -(x) : (x)) printf("%d\n", ABS(-7)); // 输出 7 ``` 2. 调试打印语句: ```c #ifdef DEBUG #define LOG(msg) fprintf(stderr, "%s\n", msg) #else #define LOG(msg) do {} while (0) #endif LOG("This message will only appear during debug builds."); ``` 3. 统一接口封装: ```c++ #ifdef _WIN32 #define CLEAR_SCREEN system("cls") #else #define CLEAR_SCREEN system("clear") #endif CLEAR_SCREEN; ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值