C语言——#define的使用

#define定义常量

基本语法

 #define name stuff
//(#define)(变量名)(定义的数值)

这里记得,是不加分号的 

定义常量(这里 就要涉及我们经常说的宏定义)

定义常量的使用 

  1. 提高代码可读性: 常量可以帮助开发者理解代码的含义。例如,使用常量 MAX_USERS 比 使用数字 100 更能表达一个变量应该表示的最大用户数。

  2. 便于维护: 如果一个值在程序中多次使用,比如一个应用的版本号,将其定义为常量(如 VERSION)可以使得未来的更新更加容易。你只需要改变常量的定义,而不是每一个出现该值的地方。

  3. 避免魔法数: 魔法数(Magic Numbers)是指在代码中直接出现的、没有解释的数字。使用常量代替魔法数可以增加代码的可读性和可维护性。

  4. 配置管理: 对于需要在不同环境中部署的应用程序,常量可以用来管理配置参数,如数据库连接字符串、API密钥等。这些值可以在不修改代码的情况下,通过外部配置文件或环境变量来设置。

  5. 条件编译: 在C语言中,可以使用条件编译指令 #ifdef#ifndef#if 等,结合常量定义来控制哪些代码应该在编译时包含或不包含。这可以用于创建跨平台的代码或者在调试版本和生产版本之间切换。

  6. 性能优化: 编译器通常会对常量表达式进行优化,因为它们的值在编译时是已知的。这可以提高程序的执行效率。

  7. 接口和API设计: 在设计库、框架或API时,常量可以用来定义固定的参数值、错误代码、状态标识等,使得用户更容易理解和使用这些接口。

#include <stdio.h>#define PI 3.14159
#define MIN_RADIUS 10.0
#define MAX_RADIUS 100.0double calculateArea(double radius) {if (radius < MIN_RADIUS || radius > MAX_RADIUS) {printf("半径必须在 %f 和 %f 之间。\n", MIN_RADIUS, MAX_RADIUS);return -1;}return PI * radius * radius;
}int main() {double radius = 20.0;double area = calculateArea(radius);if (area >= 0) {printf("半径为 %f 的圆的面积是:%.2f\n", radius, area);}return 0;
}

 定义常量使用的注意事项

 1.常量在使用期间是直接进行宏替换的

比如:

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MAX 3+5//(这里我们定义了一个常量)
int main()
{int n = 2;int m = 3;int count = n * MAX * m;//n*3+5*3=2*3+5*3=6+15=21printf("%d ", count);//此时的数值的21return 0;
}

2.定义的宏后面是不加分号的(不加分号不是不能加,而是加分号容易出错)(本质上还是直接进行宏替换)

比如

3.使用宏定义常量的时候,在还不熟悉的时候,你直接进行带入计算,不要想着直接计算宏,而是带入以后,根据运算符的顺序进行先后计算。

定义常量在编译期间的使用

当我们定义好之后,我需要知道,宏是如何在计算机里面进行运行的,首先是预处理生成.i文件(在csdn编译速通里面我们已经讲到了,这里复述一遍)

翻译环境的过程
1,我们写的代码先创建文件test.c的文件,也就是test.c,然后经过编译器的处理,生成目标文件(test.obj)也就是(obj)

2,目标文件和链接库一起经过链接器的处理,生成可执行程序。

3,生成目标文件(obj)的过程称之为编译(也就是生成obj的过程)

4,生成可执行程序的过程称之为链接。

5,最后整个我们写代码的地方也就是集成开发环境

而我们的宏定义常量的时候,直接就是在.i文件里面就已经完成了替换,.i文件也就是翻译环境里面的编译。我们了解就好。 

这里会进行替换,在.i文件里面,全部替换成常量

在 i文件里面 可以 很好的说明

当然我们,也可以这样定义 #define str for( ::);

#define str(变量名称) for( ::)(给一个循环);

什么意思呢,什么进行图解说明一下

#include <stdio.h>#define FOREVER for (;;)int main() {int count = 0;FOREVER {printf("这是第 %d 次循环\n", count);count++;// 在某种条件下退出循环if (count >= 10) {break;}}printf("已退出无限循环。\n");return 0;
}

 这里会 进行无线循环打印,但是我们给一个判断条件

续行符号

续行符号在下面的定义宏里面会二次详解,这里了解一下 

 在C语言中,续行符号用于将一行代码延续到下一行。这通常在以下情况下使用:
1. 当一行代码太长,超出了编辑器或标准推荐的80个字符的宽度限制时。
2. 为了提高代码的可读性,将长的表达式或参数列表分成多行。

续行符号是反斜杠 `\`,它放在行的末尾,表示该行将在下一行继续。在C语言中,续行符号只能在以下情况下使用:
- 在字符串字面量中,用于创建跨越多行的字符串。
- 在宏定义中,用于将宏的定义延续到下一行。
- 在预处理指令中,用于将指令延续到下一行。

下面是一些使用续行符号的例子:

1. **字符串字面量的续行**:```cchar* message = "这是一个非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常长的字符串。";```可以使用续行符号将其分成多行:```cchar* message = "这是一个非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常\非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常非常\长的字符串。";```
2. **宏定义的续行**:```c#define LONG_MACRO(x, y) x ## y \x ## _ ## y \y ## _ ## x```在这个例子中,宏 `LONG_MACRO` 被定义为三个部分的组合,每个部分都在新的一行上。
3. **预处理指令的续行**:```c#include <stdio.h> \<stdlib.h> \<string.h>```

虽然在实际中,`#include` 指令通常不使用续行符号,因为每个头文件都应该单独一行,但这个例子展示了如何使用续行符号。
请注意,续行符号不能用于一般代码的断行,比如在表达式或语句的中间。如果您需要在代码中换行,您应该将表达式或语句合理地分成多个部分,并确保每个部分都是有效的C语言表达式或语句。

当然我们也可以写成这样,后面的宏定义和运算符李米娜我们会讲解到。这里了解一下。

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

#define定义宏

基本语法:

#define name( parament-list ) stuff

其中的 parament-list 是⼀个由逗号隔开的符号表,它们可能出现在stuff中。

简单的说就是和函数差不多,在宏里面写一个类似于函数的计算方法,但是比函数运行的速度要快。

#define宏替换的使用

 在C语言中,`#define` 预处理器指令用于定义宏,这些宏可以在编译时被预处理器替换为指定的文本。

下面是一些使用 `#define` 宏替换的例子:

1. **定义一个简单的宏**:```c#define PI 3.14159#define MIN(a, b) ((a) < (b) ? (a) : (b))#define SQUARE(x) ((x) * (x))```在这些例子中,`PI` 被定义为圆周率的值,`MIN` 宏接受两个参数并返回它们中的最小值,`SQUARE` 宏接受一个参数并返回其平方。
2. **使用宏替换字符串**:```c#define GREETING "你好,世界!"```这个宏可以在代码中任何需要字符串 "你好,世界!" 的地方使用。
3. **使用宏替换代码块**:```c#define PRINT_INT(i) printf("整数:%d\n", i)```这个宏可以在代码中任何需要打印整数的地方使用。
4. **在宏中使用续行符号**:```c#define LONG_MACRO(x, y) x ## y \x ## _ ## y \y ## _ ## x```这个宏使用了续行符号 `\` 来将宏的定义延续到下一行。它将生成三个串联的字符串。
5. **在宏中包含条件编译**:```c#define DEBUG 1#if DEBUG#define LOG(msg) printf("调试信息:%s\n", msg)#else#define LOG(msg)#endif```

这里我们主要讲解1,4。因为2,3,5基本上就是定义常量,直接进行替换就可以。
下面是一个完整的例子,展示了如何在 `main` 函数中使用这些宏:

```c
#include <stdio.h>
#define PI 3.14159
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#define SQUARE(x) ((x) * (x))
#define GREETING "你好,世界!"
#define PRINT_INT(i) printf("整数:%d\n", i)
int main() {double radius = 10.0;double area = PI * SQUARE(radius);//printf("圆的面积是:%.2f\n", area);int a = 5;int b = 10;PRINT_INT(MIN(a, b));printf(GREETING "\n");return 0;
}
```

使用详解1

在这个例子中,我们使用了多个宏来简化代码,并提高了代码的可读性和可维护性。

宏定义,也就是squart(x) 就散是x乘x

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MUL(x) ((x)*(x)) 
//宏的使用有很多小的点
//1,宏是直接进行替换的,所以在需要进行宏运算的时候,要尽量多加上括号,防止因为优先级的问题导致使用错误
int main()
{int a = 3;int ret = MUL(a);printf("%d ", ret);return 0;
}

使用详解2

这里打印出来是7

宏是直接替换的 这里就变成了3+1*3+1=3+3+1=7

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#define MUL(x) ((x)*(x)) 
#define MULL(x) x+1*x+1
//宏的使用有很多小的点
//1,宏是直接进行替换的,所以在需要进行宏运算的时候,要尽量多加上括号,防止因为优先级的问题导致使用错误
int main()
{int a = 3;int ret = MUL(a);int ret1 = MULL(a);printf("%d %d", ret, ret1);return 0;
}

预处理阶段宏定义

我们这里看一下预处理

如果想变成36 我们可以加上括号

所以可以书写乘((x)*(X))这样 书写宏的时候不要吝啬括号

所以

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

#define的副作用 (带有副作⽤的宏参数)

++是有副作用的 这就是带有副作用

x+1;//不带副作⽤
x++;//带有副作⽤

副作用宏举例1

这里解释一下为什么有副作用

就比如下面的这个例子 ,首先什么定义一个宏,这里是一个三目操作符。如果我们传递的时候,把++传递过去就会导致宏的直接替换。

#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
x = 5;
y = 8;
z = MAX(x++, y++);
printf("x=%d y=%d z=%d\n", x, y, z);//输出的结果是什么?

也就是变成了

1,我们要先把++,替换进去。

2,z = ( (x++) > (y++) ? (x++) : (y++));已知 x = 5;y = 8;

3,得到z = ( (x=5++) > (y=8++) ? (x++) : (y++));这里因为是后置++,所以是先比较后++,5大于8

4,所以此时x=6,y=9,但是这里是一个三目操作符,所以会导致的情况就是满足y++的条件,所以z=(y=8++)++=9,。

5,因为后置++,就是这个运算结束之后才会进行++,这里y++两次,所以y=10,进行z判断的时候,y++一次,所以z=9

6,这里我们需要知道,++是会改变数值的,也就是++上去的数值,数值是会进行变化的

z = ( (x++) > (y++) ? (x++) : (y++));
x=6 y=10 z=9

宏替换的潜规则

这里还是拿上个例子来进行举例 

这里每一次都进行++

这里我们看一下预处理阶段发生的事情

‘M’这里的字符在预处理阶段是不会被搜索到的,哪怕定义了宏M 

宏替换的规则

在程序中扩展#define定义符号和宏时,需要涉及⼏个步骤。

1. 在调⽤宏时,⾸先对参数进⾏检查,看看是否包含任何由#define定义的符号。如果是,它们⾸先

被替换。

2. 替换⽂本随后被插⼊到程序中原来⽂本的位置。对于宏,参数名被他们的值所替换。

3. 最后,再次对结果⽂件进⾏扫描,看看它是否包含任何由#define定义的符号。如果是,就重复上

述处理过程。

注意:

1. 宏参数和#define 定义中可以出现其他#define定义的符号。但是对于宏,不能出现递归。

2. 当预处理器搜索#define定义的符号的时候,字符串常量的内容并不被搜索。

————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————

宏和函数的对比

 宏(Macro)和函数(Function)是编程语言中的两个重要概念,它们在代码中执行特定任务,但它们之间存在一些关键的区别。以下是宏和函数的对比:

1. **定义和替换**:

- **宏**:在编译前,预处理器会替换宏调用。宏可以是对一个词条的简单替换,也可以包含更复杂的文本生成。
 - **函数**:函数是一段可以被重复调用的代码块,它在程序运行时被调用和执行。


2. **展开**:

 - **宏**:宏会在编译前被展开,因此宏调用不会增加程序的运行时间。
 - **函数**:函数调用会在程序运行时执行,通常会增加程序的运行时间。


3. **参数传递**:

 - **宏**:宏通常不支持参数传递,或者只在宏定义中做文字替换,不进行参数的动态替换。
 - **函数**:函数可以接受参数,并且根据传入的参数执行不同的代码。

4. **可变性**:

 - **宏**:宏在定义时通常是不可变的,它们不会根据程序的运行状态改变。
  - **函数**:函数内部可以有变量的声明和使用,这些变量在函数的作用域内是可变的。

5. **目的**:

 - **宏**:宏主要用于文本替换,比如简化代码、创建标识符等。
 - **函数**:函数用于封装可重用的代码块,实现特定的功能。

6. **效率**:

 - **宏**:由于宏在编译前就被展开,所以理论上它们的执行效率高于函数调用。
 - **函数**:函数调用可能比宏展开慢,因为它涉及到跳转和栈帧的创建,但是对于复杂的代码逻辑,函数可以提高代码的可读性和可维护性。

7. **适用场景**:

- **宏**:宏适用于简单的文本替换,或者在编译器级别需要进行的一些特殊处理。
- **函数**:函数适用于需要重复执行且带有逻辑处理的代码块。
在实际的编程实践中,宏和函数的选择取决于具体的需求和上下文。在需要优化性能时,可以考虑使用宏;而在需要代码抽象和模块化时,函数是更好的选择。在高级编程语言中,宏通常作为语言提供的一种机制,而函数则是核心的语言特性。 

函数 

函数的代码 反汇编,运算的完成需要十几条指令

宏定义会产生的情况

这里的一套指令产生的汇编代码是比这个函数少的

宏的参数是没有类型的我们是完成替换的

但是宏通常是解简单运算的适合小型运算 不适合大型的运算。

那为什么不⽤函数来完成这个任务?

原因有⼆:

1. ⽤于调⽤函数和从函数返回的代码可能⽐实际执⾏这个⼩型计算⼯作所需要的时间更多。所以宏⽐

函数在程序的规模和速度⽅⾯更胜⼀筹。

2. 更为重要的是函数的参数必须声明为特定的类型。所以函数只能在类型合适的表达式上使⽤。反之

这个宏怎可以适⽤于整形、⻓整型、浮点型等可以⽤于 > 来⽐较的类型。宏的参数是类型⽆关

的。

宏的劣势

可能会产生,宏替代的前后的代码你看见的可能是不一样的,也就是调试的时候可能是不方便调试的。

和函数相⽐宏的劣势:

1. 每次使⽤宏的时候,⼀份宏定义的代码将插⼊到程序中。除⾮宏⽐较短,否则可能⼤幅度增加程序

的⻓度。

2. 宏是没法调试的。

3. 宏由于类型⽆关,也就不够严谨。

4. 宏可能会带来运算符优先级的问题,导致程容易出现错。

宏可以做到函数做不到的事情

宏的参数可以出现类型,什么意思呢,简单的说就是,有些计算公式里面是有类型的,可能是int类型,可能是char类型。

这个图解里面,我们可以看到,我们是可以定义类型的,并且不需要进行强制类型转化

这里我们传递一个数值,所以就变成了,Malloc(10,int)->

(int*)malloc(10*sizeof(int));

最后的效果和int*p是一样的 

宏和函数的对比

也就是相对简单的时候用宏解决,相对难的时候用函数

宏的应用 

C语言-写一个宏,可以将一个整数的二进制位的奇数位和偶数位交换。-CSDN博客https://blog.csdn.net/Jason_from_China/article/details/137179856

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/299734.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

网络安全 | 什么是威胁情报?

关注WX&#xff1a;CodingTechWork 威胁情报 威胁情报-介绍 威胁情报也称为“网络威胁情报”(CTI)&#xff0c;是详细描述针对组织的网络安全威胁的数据。威胁情报可帮助安全团队更加积极主动地采取由数据驱动的有效措施&#xff0c;在网络攻击发生之前就将其消弭于无形。威…

Linux-线程知识点

目录 线程与进程区别pthread库接口介绍pthread_createpthread_self和syscall(SYS_gettid);pthread_equal测试主线程的栈空间大概是多大pthread_setname_nppthread_exitpthread_join为什么要连接退出的线程 pthread_detach 线程与进程区别 进程是一个动态的实体&#xff0c;有自…

大数据实验三-HBase编程实践

目录 一&#xff0e;实验内容 二&#xff0e;实验目的 三&#xff0e;实验过程截图及说明 1、安装HBase 2、配置伪分布式模式&#xff1a; 3、使用hbase的shell命令来操作表&#xff1a; 4、使用hbase提供的javaAPI来编程实现类似操作&#xff1a; 5、实验总结及心得体会…

Linux文件IO(4):目录操作和文件属性获取

目录 1. 前言 2. 函数介绍 2.1 访问目录 – opendir 2.2 访问目录 – readdir 2.3 访问目录 – closedir 2.4 修改文件访问权限 – chmod/fchmod 2.5 获取文件属性 – stat/lstat/fstat 2.5.1 文件属性 – struct stat 2.6 文件类型 – st_mode 3. 代码练习 3.1 要求 3.2 代…

(十一)RabbitMQ及SpringAMQP

1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&#xff0c;…

2024-04-03 NO.4 Quest3 手势追踪抓取物体

文章目录 1 手势抓取方式1.1 Hand Grab1.2 Touch Hand Grab1.3 Distance Hand Grab 2 HandGrabExamples 示例场景2.1 Interactor 对象2.2 Interactable 对象2.2.1 父子结构2.2.2 “Hand Grab lnteractable” 脚本2.2.3 “Move Towards Target Provider” 脚本2.2.4 其他 Moveme…

linux常用目录结构(目录命令)--6986字详谈

前面与大家讨论了linux的发展与由来&#xff08;这一块挺多的&#xff0c;小编还没有编写完成&#xff0c;希望大家理解&#xff09;&#xff0c;紧接着谈到了vmware安装及运行所存在的故障&#xff08;鉴定错误&#xff0c;虚拟机没有网&#xff0c;蓝屏等常见现象的总结及处理…

Day105:代码审计-PHP原生开发篇SQL注入数据库监控正则搜索文件定位静态分析

目录 代码审计-学前须知 Bluecms-CNVD-1Day-常规注入审计分析 emlog-CNVD-1Day-常规注入审计分析 emlog-CNVD-1Day-2次注入审计分析 知识点&#xff1a; 1、PHP审计-原生态开发-SQL注入&语句监控 2、PHP审计-原生态开发-SQL注入&正则搜索 3、PHP审计-原生态开发-SQ…

Java 接口提示500,但console并不报错。

因为习惯了C语言printf打印&#xff0c;且当时并不明白try catch意义所在 如图所示&#xff0c;下添加了行号打印 但只打印出了line 89&#xff0c;无line 91&#xff0c;也无报错 所以使用try catch 包裹Sql查询封装函数 e.printStackTrace(); 果真打印出了 查看Entity类&…

【C++初阶】String在OJ中的使用(一):仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加

前言&#xff1a; &#x1f3af;个人博客&#xff1a;Dream_Chaser &#x1f388;博客专栏&#xff1a;C &#x1f4da;本篇内容&#xff1a;仅仅反转字母、字符串中的第一个唯一字母、字符串最后一个单词的长度、验证回文串、字符串相加 目录 917.仅仅反转字母 题目描述&am…

docker基础学习指令

文章目录 [toc] docker基础常用指令一、docker 基础命令二、docker 镜像命令1. docker images2. docker search3. docker pull4. docker system df5. docker rmi1. Commit 命令 三、 docker 容器命令1. docker run2. docker logs3. docker top4. docker inspect5. docker cp6. …

语音特征的反应——语谱图

语谱图的横坐标为时间&#xff0c;纵坐标为对应时间点的频率。坐标中的每个点用不同颜色表示&#xff0c;颜色越亮表示频率越大&#xff0c;颜色越淡表示频率越小。可以说语谱图是一个在二维平面展示三维信息的图,既能够表示频率信息,又能够表示时间信息。 创建和绘制语谱图的…

相位导数方差计算-matlab

%% 下面计算 相位导数方差% 假设 phase_map 是你的相位图二维矩阵 % K 是窗口的大小 k 3; % 请使用实际的窗口大小替换% 计算 x 和 y 方向的偏导 [dx, dy] gradient(wrappedPhase); Ksq k^2; % 计算 K^2half_k floor(k / 2);% 初始化结果矩阵 result zeros(size(wrappedPh…

CSRF介绍及Python实现

CSRF 文章目录 CSRF1. CSRF是什么&#xff1f;2. CSRF可以做什么&#xff1f;3. CSRF漏洞现状4. CSRF的原理5. 举例说明6. CSRF的防御Python示例 1. CSRF是什么&#xff1f; CSRF&#xff08;Cross-Site Request Forgery&#xff09;&#xff0c;中文名称&#xff1a;跨站请求…

Object 类的使用

文章目录 1、 如何理解根父类2、 Object类的方法1、equals()2、toString()3、getClass()4、hashCode()5、clone()6、finalize() 1、 如何理解根父类 类 java.lang.Object是类层次结构的根类&#xff0c;即所有其它类的父类。每个类都使用 Object 作为超类。 Object类型的变量与…

顺序表的应用之通讯录

学习了顺序表之后&#xff0c;我们也得知道它的实际用途吧&#xff01;所以&#xff0c;我们今天来学习一下通讯录的实现。 typedef struct personInfo SLDataType; contact.h #define NAME_MAX 20 #define GENDER_MAX 20 #define GTEL_MAX 20 #define ADDR_MAX 100 #include&…

牛客 2024春招冲刺题单 ONT98 牛牛猜节点【中等 斐波那契数列 Java,Go,PHP】

题目 题目链接&#xff1a; https://www.nowcoder.com/practice/6a3dfb5be4544381908529dc678ca6dd 思路 斐波那契数列参考答案Java import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定&#xff0c;请勿修改&#xff0c;直接返回方法规…

【Django开发】0到1美多商城项目md教程第5篇:短信验证码,1. 避免频繁发送短信验证码逻辑分析【附代码文档】

美多商城完整教程&#xff08;附代码资料&#xff09;主要内容讲述&#xff1a;欢迎来到美多商城&#xff01;&#xff0c;项目准备。展示用户注册页面&#xff0c;创建用户模块子应用。用户注册业务实现&#xff0c;用户注册前端逻辑。图形验证码&#xff0c;图形验证码接口设…

linux------jekins构建cicd

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;linux &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&#…

Vue3:用Pinia的storeToRefs结构赋值store数据

一、情景描述 我们学习了Pinia之后&#xff0c;知道&#xff0c;数据是配置在Pinia的state里面的。 那么&#xff0c;如果有多个字段需要取出来使用&#xff0c;并且不丢失数据的响应式&#xff0c;如何优雅的操作了&#xff1f; 这里就用到了Pinia的storeToRefs函数 二、案…