C语言 --- 指针(5)
目录
一.sizeof和strlen对比
1.sizeof
2.strlen
3.strlen 和sizeof的对比
二.数组和指针笔试题目详解
回顾:数组名的理解
1.一维数组
2.字符数组
代码1:
代码2:
代码3:
代码4:
代码5:
代码6:
3.二维数组
总结
一.sizeof和strlen对比
1.sizeof
sizeof既是一种关键字也是一个操作符。sizeof的作用是计算变量和类型的所占内存空间的大小,单位是字节,返回size_t类型的值。sizeof只关注所占用内存空间的大小,不在乎内存中存放的什么数据。
比如:
#include<stdio.h>
int main()
{int a = 10;printf("%d\n",sizeof(a));printf("%d\n",sizeof a );printf("%d\n",sizeof(int));return 0;
}
sizeof在使用时,可以不用括号,这证明了它不是一个函数,但是在计算类型比如int就不行,必须加括号。
打印结果都是4,size_t类型的值应该用%zd打印,但是这里也可以使用%d,只不过编译器会发出警告,但是影响不大。
sizeof不关注括号中的数据,只关注存放内存的大小。比如:
#include<stdio.h>
int main()
{int a = 10;int size = sizeof(a++);printf("%d\n",size);printf("%d\n",a);return 0;
}
输出结果是4 10
很明显sizeof括号中的表达式是没有计算的。
2.strlen
strlen是C语言库函数,在使用时需要包含头文件<string.h>
函数原型:
size_t strlen(const char *str);
这个函数会返回字符串中字符数,但是不包括\0,也就是返回的是\0之前的字符数。如果没有\0就会出现越界查找的情况。
比如:
#include<stdio.h>
int main()
{char arr1[] = {'a','b','c'};char arr2[] ="abc" ;printf("%d\n",strlen(arr1));printf("%d\n",strlen(arr2));printf("%d\n",sizeof(arr1));printf("%d\n",sizeof(arr2));return 0;
}
打印结果是 随机值 3 3 4.
第一个是随机值的原因就是没有\0,strlen会一直查找直到遇到\0才终止。
第二个因为是常量字符串,包含\0,所以是3。
第三个计算的是数组arr1中所占内存的大小,只有三个字符,也就是3个字节。
第四个arr2中有\0,所以是4个字节。
3.strlen 和sizeof的对比
sizeof | strlen |
|
|
二.数组和指针笔试题目详解
回顾:数组名的理解
数组名是数组首元素的地址。
但是有两个的特殊情况
- sizeof(数组名) ,sizeof中单独放数组名,这里的数组名表示的是整个数组,计算的是整个数组的大小,单位是字节。
- &数组名,这里的数组名代表的是整个数组,&取出的是整个数组的地址。(整个数组的地址虽然和数组首元素的地址是相同的,但是指针变量的类型是不同的。)
1.一维数组
#include<stdio.h>
int main()
{int a[] = { 1,2,3,4 };printf("%d\n", sizeof(a));//1printf("%d\n", sizeof(a + 0));//2printf("%d\n", sizeof(*a));//3printf("%d\n", sizeof(a + 1));//4printf("%d\n", sizeof(a[1]));//5printf("%d\n", sizeof(&a));//6printf("%d\n", sizeof(*&a));//7printf("%d\n", sizeof(&a + 1));//8printf("%d\n", sizeof(&a[0]));//9printf("%d\n", sizeof(&a[0] + 1));//10return 0;
}
序号 | 解析 | 答案 |
1 | a是数组名,sizeof中单独放数组名,计算的是整个数组的大小,单位字节。 | 16 |
2 | sizeof中没有单独放数组名a,所以这里的数组名就是数组首元素的地址,地址就是指针变量。在不同环境下大小不同。 | 4 || 8 |
3 | a是数组首元素的地址,解引用后得到数组首元素。所以计算的是整形变量的大小。 | 4 |
4 | a表示数组首元素的地址,地址就是指针,类型是int*,指针加1跳过4个字节,也就是一个整形元素,也就是第二个元素的地址。 | 4 || 8 |
5 | a[1]表示数组第二个元素 | 4 |
6 | &a是整个数组的地址,地址就是指针变量. | 4 || 8 |
7 | &a是整个数组的地址,解引用后就是整个数组。所以sizeof计算的是整个数组的大小(&和*可以相互抵消) | 16 |
8 | &a是整个数组的地址,+1跳过了整个数组,虽然这个地址并没有指向这个数组了,但是我们并没有越界访问,所以不影响sizeof计算这个指针变量的大小。 | 4 || 8 |
9 | &a[0]得到的是数组首元素的地址. | 4 || 8 |
10 | &a[0]+1,跳过一个元素,得到的是数组第二个元素的地址。 | 4 || 8 |
2.字符数组
代码1:
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7
序号 | 解析 | 答案 |
1 | arr单独放在sizeof中,计算的是整个数组的大小。单位字节 | 6 |
2 | arr没有单独放在数组中,arr表示的是数组首元素的地址 | 4 || 8 |
3 | arr表示的是数组首元素的地址,解引用后得到的是数组首元素。 | 1 |
4 | arr[1]表示数组首元素。 | 1 |
5 | &arr表示整个数组的地址,地址就是指针变量 | 4 || 8 |
6 | &a是整个数组的地址,+1跳过了整个数组,虽然这个地址并没有指向这个数组了,但是我们并没有越界访问,所以不影响sizeof计算这个指针变量的大小。 | 4 || 8 |
7 | &arr[0]表示数组首元素的地址,+1跳过一个元素,表示数组第二个元素的地址 | 4 || 8 |
代码2:
char arr[] = {'a','b','c','d','e','f'};
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));//5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7
序号 | 解析 | 答案 |
1 | arr是数组首元素的地址,strlen计算的是'\0'之前的字符个数,但是这个数组中并没有'\0',所以会出现越界的情况,故无法出现准确的值的情况。 | 随机值 |
2 | 这里的arr也是数组首元素的地址,+0并没有跳过任何字节,与序号1同理也是不确定情况。(两个值应该是一样的) | 随机值 |
3 | strlen的参数是const char *类型的。*arr得到的是数组首元素,将这个作为参数传给strlen是不行的,这里程序会崩溃。 | error |
4 | arr[1]表示数组第二个元素,将其作为参数传给strlen是不行的。 | error |
5 | &arr表示整个数组的地址,虽然是一个数组指针变量,但是传参会进行强制类型转换为char*类型,值和数组首元素的地址相同,所以和序号1和2相同,值一样的。 | 随机值 |
6 | &a是整个数组的地址,+1跳过了整个数组,也就是跳过了6个字节。但是因为没有'\0',也会出现随机的情况 | 随机值(比序号125小6) |
7 | &arr[0]表示数组首元素的地址,+1跳过一个元素,表示数组第二个元素的地址,只跳过了1个字节。 | 随机值(比序号125小1) |
输出结果:(以下是随机值,不是特定情况。)
序号3和4已被注释掉了。
代码3:
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));//1
printf("%d\n", sizeof(arr+0));//2
printf("%d\n", sizeof(*arr));//3
printf("%d\n", sizeof(arr[1]));//4
printf("%d\n", sizeof(&arr));//5
printf("%d\n", sizeof(&arr+1));//6
printf("%d\n", sizeof(&arr[0]+1));//7
序号 | 解析 | 答案 |
1 | sizeof(数组名),计算的是整个数组的大小,字符串末尾是有一个'\0'的,只不过没有显示出来,我们可以通过调试观察,所以这个字符串中有7个字符。 | 7 |
2 | 这里的arr也是数组首元素的地址,+0并没有跳过任何字节,是一个指针变量。 | 4 || 8 |
3 | *arr的到的数组首元素。 | 1 |
4 | arr[1]表示数组第二个元素. | 1 |
5 | &arr表示整个数组的地址,是一个指针变量。 | 4 || 8 |
6 | &a是整个数组的地址,+1跳过了整个数组,但是还是一个指针变量 | 4 || 8 |
7 | &arr[0]表示数组首元素的地址,+1跳过一个元素,表示数组第二个元素的地址,是一个指针变量 | 4 || 8 |
序号1:
我们可以看到数组中分别放着不同的字符,字符前面是它们的ASCII码值,arr[6],也就是数组的第7个元素,存放着'\0'字符。
代码4:
char arr[] = "abcdef";
printf("%d\n", strlen(arr));//1
printf("%d\n", strlen(arr+0));//2
printf("%d\n", strlen(*arr));//3
printf("%d\n", strlen(arr[1]));//4
printf("%d\n", strlen(&arr));//5
printf("%d\n", strlen(&arr+1));//6
printf("%d\n", strlen(&arr[0]+1));//7
序号 | 解析 | 答案 |
1 | sizeof计算的是'\0'之前的地址,有6个字符 | 6 |
2 | sizeof计算的是'\0'之前的地址,有6个字符 | 6 |
3 | *arr的到的数组首元素。不应该作为参数传给strlen | error |
4 | arr[1]表示数组第二个元素.不应该作为参数传给strlen | error |
5 | &arr表示整个数组的地址,sizeof计算的是'\0'之前的地址,有6个字符. | 6 |
6 | &a是整个数组的地址,+1跳过了整个数组,故不知道什么时候会遇到'\0',所以是个随机值 | 随机值 |
7 | &arr[0]表示数组首元素的地址,+1跳过一个元素,表示数组第二个元素的地址,从第二个开始到'\0',有5个字节。 | 5 |
输出结果:
序号6就是经过了16个字符才遇到'\0',error情况已经注释掉了。
代码5:
char *p = "abcdef";
printf("%d\n", sizeof(p));//1
printf("%d\n", sizeof(p+1));//2
printf("%d\n", sizeof(*p));//3
printf("%d\n", sizeof(p[0]));//4
printf("%d\n", sizeof(&p));//5
printf("%d\n", sizeof(&p+1));//6
printf("%d\n", sizeof(&p[0]+1);//7
序号 | 解析 | 答案 |
1 | sizeof计算的是'\0'之前的地址,有6个字符 | 6 |
2 | sizeof计算的是'\0'之前的地址,有6个字符 | 6 |
3 | *arr的到的数组首元素。不应该作为参数传给strlen | error |
4 | arr[1]表示数组第二个元素.不应该作为参数传给strlen | error |
5 | &arr表示整个数组的地址,sizeof计算的是'\0'之前的地址,有6个字符. | 6 |
6 | &a是整个数组的地址,+1跳过了整个数组,故不知道什么时候会遇到'\0',所以是个随机值 | 随机值 |
7 | &arr[0]表示数组首元素的地址,+1跳过一个元素,表示数组第二个元素的地址,从第二个开始到'\0',有5个字节。 | 5 |
代码6:
char *p = "abcdef";
printf("%d\n", strlen(p));//1
printf("%d\n", strlen(p+1));//2
printf("%d\n", strlen(*p));//3
printf("%d\n", strlen(p[0]));//4
printf("%d\n", strlen(&p));//5
printf("%d\n", strlen(&p+1));//6
printf("%d\n", strlen(&p[0]+1));//7
序号 | 解析 | 答案 |
1 | sizeof计算的是'\0'之前的地址,有6个字符 | 6 |
2 | sizeof计算的是'\0'之前的地址,+1后跳过一个字节,也就是一个元素,有5个字符 | 5 |
3 | *p的到的数组首元素。不应该作为参数传给strlen | error |
4 | p[0]表示数组第一个元素.不应该作为参数传给strlen | error |
5 | &p表示字符指针的地址,sizeof计算的是'\0'之前的地址,会产生随机值 | 随机值 |
6 | &p是字符指针的地址,加1 跳过4 || 8个字节,故不知道什么时候会遇到'\0',所以是个随机值 | 随机值 |
7 | &p[0]表示首首字符的地址,+1跳过一个元素,表示第二个字符的地址,从第二个开始到'\0',有5个字节。 | 5 |
输出结果:
3.二维数组
int a[3][4] = {0};
printf("%d\n",sizeof(a));//1
printf("%d\n",sizeof(a[0][0]));//2
printf("%d\n",sizeof(a[0]));//3
printf("%d\n",sizeof(a[0]+1));//4
printf("%d\n",sizeof(*(a[0]+1)));//5
printf("%d\n",sizeof(a+1));//6
printf("%d\n",sizeof(*(a+1)));//7
printf("%d\n",sizeof(&a[0]+1));//8
printf("%d\n",sizeof(*(&a[0]+1)));//9
printf("%d\n",sizeof(*a));//10
printf("%d\n",sizeof(a[3]));//11
序号 | 解析 | 答案 |
1 | 数组名a单独放在sizeof中,计算的是整个数组的大小。 | 48 = 3 * 4 * sizeof(int) |
2 | a[0][0]表示数组第一行第一个元素。 | 4 |
3 |
| 4 * sizeof(int) = 16 |
4 | a[0]表示第一个一维数组的数组名,并没有单独放在sizeof中,代表首元素的地址,+1,跳过一个元素,也就是&a[0][1]. | 4 || 8 |
5 | 解引用后得到的是a[0][1] | 4 |
6 | a表示数组首元素的地址,+1就是第二个元素的地址,也就是第二个一维数组的地址, | 4 || 8 |
7 | 解引用后就是第二个一维数组。 | 16 |
8 | a[0]是第一行的数组名,&a[0]就是第一行的地址,+1后是第二行的地址,地址就是指针 | 4 || 8 |
9 | 解引用后就是第二行,计算的第二行的大小 | 16 |
10 | *a就是第一行,计算的就是第一行的大小 | 16 |
11 | a[3]是第四行的数组名,虽然没有第四行,但是sizeof并没有进行访问,所以并不是越界访问,根据类型仍然可以计算第四行的大小,4个整形变量。 | 16 |
总结
数组名的意义:
- sizeof(数组名),这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩。
- & 数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址。
- 除此之外所有的数组名都表⽰⾸元素的地址。
相关文章:

C语言 --- 指针(5)
目录 一.sizeof和strlen对比 1.sizeof 2.strlen 3.strlen 和sizeof的对比 二.数组和指针笔试题目详解 回顾:数组名的理解 1.一维数组 2.字符数组 代码1: 代码2: 代码3: 代码4: 代码5: 代码6&am…...

Android Studio Iguana | 2023.2.1版本
Android Gradle 插件和 Android Studio 兼容性 Android Studio 构建系统基于 Gradle,并且 Android Gradle 插件 (AGP) 添加了一些特定于构建 Android 应用程序的功能。下表列出了每个版本的 Android Studio 所需的 AGP 版本。 如果特定版本的 Android Studio 不支持…...

并查集(蓝桥杯 C++ 题目 代码 注解)
目录 介绍: 模板: 题目一(合根植物): 代码: 题目二(蓝桥幼儿园): 代码: 题目三(小猪存钱罐): 代码: …...

MapReduce内存参数自动推断
MapReduce内存参数自动推断。在Hadoop 2.0中,为MapReduce作业设置内存参数非常繁琐,涉及到两个参数:mapreduce.{map,reduce}.memory.mb和mapreduce.{map,reduce}.java.opts,一旦设置不合理,则会使得内存资源浪费严重&a…...
pyside6 pytq PyDracula QVideoWidget视频只有画面没有声音
解决方案: 先不使用框架,纯pyside6代码,如果添加视频有画面有声音,那可以排除是硬件问题,如果没有画面只有声音,可能是视频解码器无法解码,换个格式的视频文件如果只有使用PyDracula 出问题&am…...

Axure基础 各元件的作用及介绍
图像热区 增加按钮或者文本的点击区域,他是透明的,在预览时看不见。 动态面板 用来绘制一下带交互效果的元件,他是动态的,如轮播图,一个动态面板里可以有多个子面板,每一个子面板对应着不同的效果。 他…...

学习Java的第六天
目录 一、变量 1、变量的定义 2、变量的声明格式 3、变量的注意事项 4、变量的作用域 二、常量 三、命名规范 Java 语言支持如下运算符: 1、算术运算符 解析图: 示例: 2、赋值运算符 解析图: 示例: 3、关…...

基于Spring Boot+ Vue的房屋租赁系统
末尾获取源码作者介绍:大家好,我是墨韵,本人4年开发经验,专注定制项目开发 更多项目:CSDN主页YAML墨韵 学如逆水行舟,不进则退。学习如赶路,不能慢一步。 目录 一、项目简介 二、开发技术与环…...
多轨迹建模方法的介绍与实操-基于R语言
本文介绍了多轨迹建模方法(Group-Based Multivariate Trajectory Modeling),这是一种扩展了单指标组基轨迹建模的技术,用于分析多个疾病生物标志物或临床重要因素的联合轨迹,以更好地理解和追踪疾病进程、行为或健康状…...

【Spring】Spring状态机
1.什么是状态机 (1). 什么是状态 先来解释什么是“状态”( State )。现实事物是有不同状态的,例如一个自动门,就有 open 和 closed 两种状态。我们通常所说的状态机是有限状态机,也就是被描述的事物的状态的数量是有…...
Node.js基础---使用Express写接口
1. 创建基本的服务器 2. 创建 API 路由模块 // aoiRouter.js 路由模块 const express require(express) const apiRouter express.Router()module.exports apiRouter// ------------------------------------------// app.js 导入并注册路由模块 const apiRouter require(…...
小蓝的钥匙(蓝桥杯错排)
现在有28个小朋友,每个人手上有一把钥匙,每一个钥匙都只能打开自己的房间门,现在将所有钥匙都收上来,然后再随机打乱分给每个小朋友,也就是有28!的分法,请问现在其中14个小朋友的钥匙能恰好打开…...

【Python】科研代码学习:八 FineTune PretrainedModel (用 trainer,用 script);LLM文本生成
【Python】科研代码学习:八 FineTune PretrainedModel [用 trainer,用 script] LLM文本生成 自己整理的 HF 库的核心关系图用 trainer 来微调一个预训练模型用 script 来做训练任务使用 LLM 做生成任务可能犯的错误,以及解决措施 自己整理的 …...
SpringBoot RestTemplate远程调用总结
1、get请求 GetMapping("/searchEntryRecordPageList") public JSONObject searchEntryRecordPageList(RequestParam Map<String,Object> params){HttpHeaders requestHeaders new HttpHeaders();requestHeaders.add("Authorization","Bearer…...

Python 强大邮件处理库 Imbox
目录 IMAP Mailbox Imbox 安装 特性 提取邮件内容 处理附件 安全性 示例 1:读取收件箱中的邮件 2:搜索并下载附件 3:连接到IMAP服务器获取所有邮件 结论 IMAP Mailbox IMAP(Internet Message Access Protocol&#x…...

ElasticSearch深度分页问题如何解决
文章目录 概述解决方法深度分页方式from size深度分页之scrollsearch_after 三种分页方式比较 概述 Elasticsearch 的深度分页问题是指在大数据集上进行大量分页查询时可能导致的性能下降和资源消耗增加的情况。这种情况通常发生在需要访问大量数据的情形下,比如用…...
景安空间不支持指定运行目录tp5
/WEB/public/.htaccess配置 <IfModule mod_rewrite.c> Options FollowSymlinks -Multiviews RewriteEngine on RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^(.*)$ index.php?s$1 [QSA,PT,L] </IfModule>. 2./WEB/.ht…...

开放式高实时高性能PLC控制器解决方案-基于米尔电子STM32MP135
前言 随着工业数字化进程加速与IT/OT深入融合,不断增加的OT核心数据已经逐步成为工业自动化行业的核心资产,而OT层数据具备高实时、高精度、冗余度高、数据量大等等特点,如何获取更加精准的OT数据对数字化进程起到至关重要的作用,…...
【MySQL】-MVCC多版本并发控制
1、当前读 select 不加锁状态,当前读快照读 2、快照读 在select加锁下,读取数据后,形成快照。每个事务都会形成自己的快照内容 SELECT * FROM xx_table LOCK IN SHARE MODE;SELECT * FROM xx_table FOR UPDATE;INSERT INTO xx_table ...D…...

mangoDB:2024安装
mangoDB:2024安装 mangoDB: 下载链接 取消勾选 配置环境变量 启动服务 同级目录下创建一个db文件夹 然后执行命令,启动服务 mongod --dbpath D:\environment\mango\db访问http://localhost:27017/ 出现下面的就是安装成功 2然后在管理员权限下给mango服务重…...
Cursor实现用excel数据填充word模版的方法
cursor主页:https://www.cursor.com/ 任务目标:把excel格式的数据里的单元格,按照某一个固定模版填充到word中 文章目录 注意事项逐步生成程序1. 确定格式2. 调试程序 注意事项 直接给一个excel文件和最终呈现的word文件的示例,…...
macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用
文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...
VTK如何让部分单位不可见
最近遇到一个需求,需要让一个vtkDataSet中的部分单元不可见,查阅了一些资料大概有以下几种方式 1.通过颜色映射表来进行,是最正规的做法 vtkNew<vtkLookupTable> lut; //值为0不显示,主要是最后一个参数,透明度…...
【服务器压力测试】本地PC电脑作为服务器运行时出现卡顿和资源紧张(Windows/Linux)
要让本地PC电脑作为服务器运行时出现卡顿和资源紧张的情况,可以通过以下几种方式模拟或触发: 1. 增加CPU负载 运行大量计算密集型任务,例如: 使用多线程循环执行复杂计算(如数学运算、加密解密等)。运行图…...

SAP学习笔记 - 开发26 - 前端Fiori开发 OData V2 和 V4 的差异 (Deepseek整理)
上一章用到了V2 的概念,其实 Fiori当中还有 V4,咱们这一章来总结一下 V2 和 V4。 SAP学习笔记 - 开发25 - 前端Fiori开发 Remote OData Service(使用远端Odata服务),代理中间件(ui5-middleware-simpleproxy)-CSDN博客…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf
FTP 客服管理系统 实现kefu123登录,不允许匿名访问,kefu只能访问/data/kefu目录,不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

通过MicroSip配置自己的freeswitch服务器进行调试记录
之前用docker安装的freeswitch的,启动是正常的, 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...

9-Oracle 23 ai Vector Search 特性 知识准备
很多小伙伴是不是参加了 免费认证课程(限时至2025/5/15) Oracle AI Vector Search 1Z0-184-25考试,都顺利拿到certified了没。 各行各业的AI 大模型的到来,传统的数据库中的SQL还能不能打,结构化和非结构的话数据如何和…...

【Linux】Linux安装并配置RabbitMQ
目录 1. 安装 Erlang 2. 安装 RabbitMQ 2.1.添加 RabbitMQ 仓库 2.2.安装 RabbitMQ 3.配置 3.1.启动和管理服务 4. 访问管理界面 5.安装问题 6.修改密码 7.修改端口 7.1.找到文件 7.2.修改文件 1. 安装 Erlang 由于 RabbitMQ 是用 Erlang 编写的,需要先安…...