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服务重…...
多场景 OkHttpClient 管理器 - Android 网络通信解决方案
下面是一个完整的 Android 实现,展示如何创建和管理多个 OkHttpClient 实例,分别用于长连接、普通 HTTP 请求和文件下载场景。 <?xml version"1.0" encoding"utf-8"?> <LinearLayout xmlns:android"http://schemas…...
【RockeMQ】第2节|RocketMQ快速实战以及核⼼概念详解(二)
升级Dledger高可用集群 一、主从架构的不足与Dledger的定位 主从架构缺陷 数据备份依赖Slave节点,但无自动故障转移能力,Master宕机后需人工切换,期间消息可能无法读取。Slave仅存储数据,无法主动升级为Master响应请求ÿ…...
在鸿蒙HarmonyOS 5中使用DevEco Studio实现录音机应用
1. 项目配置与权限设置 1.1 配置module.json5 {"module": {"requestPermissions": [{"name": "ohos.permission.MICROPHONE","reason": "录音需要麦克风权限"},{"name": "ohos.permission.WRITE…...
GruntJS-前端自动化任务运行器从入门到实战
Grunt 完全指南:从入门到实战 一、Grunt 是什么? Grunt是一个基于 Node.js 的前端自动化任务运行器,主要用于自动化执行项目开发中重复性高的任务,例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...
C#中的CLR属性、依赖属性与附加属性
CLR属性的主要特征 封装性: 隐藏字段的实现细节 提供对字段的受控访问 访问控制: 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性: 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑: 可以…...
C# 表达式和运算符(求值顺序)
求值顺序 表达式可以由许多嵌套的子表达式构成。子表达式的求值顺序可以使表达式的最终值发生 变化。 例如,已知表达式3*52,依照子表达式的求值顺序,有两种可能的结果,如图9-3所示。 如果乘法先执行,结果是17。如果5…...
Linux系统部署KES
1、安装准备 1.版本说明V008R006C009B0014 V008:是version产品的大版本。 R006:是release产品特性版本。 C009:是通用版 B0014:是build开发过程中的构建版本2.硬件要求 #安全版和企业版 内存:1GB 以上 硬盘…...
华为OD机试-最短木板长度-二分法(A卷,100分)
此题是一个最大化最小值的典型例题, 因为搜索范围是有界的,上界最大木板长度补充的全部木料长度,下界最小木板长度; 即left0,right10^6; 我们可以设置一个候选值x(mid),将木板的长度全部都补充到x,如果成功…...
Modbus RTU与Modbus TCP详解指南
目录 1. Modbus协议基础 1.1 什么是Modbus? 1.2 Modbus协议历史 1.3 Modbus协议族 1.4 Modbus通信模型 🎭 主从架构 🔄 请求响应模式 2. Modbus RTU详解 2.1 RTU是什么? 2.2 RTU物理层 🔌 连接方式 ⚡ 通信参数 2.3 RTU数据帧格式 📦 帧结构详解 🔍…...
鸿蒙(HarmonyOS5)实现跳一跳小游戏
下面我将介绍如何使用鸿蒙的ArkUI框架,实现一个简单的跳一跳小游戏。 1. 项目结构 src/main/ets/ ├── MainAbility │ ├── pages │ │ ├── Index.ets // 主页面 │ │ └── GamePage.ets // 游戏页面 │ └── model │ …...
