C语言——深入理解指针(2)(数组与指针)
文章目录
- 数组名的理解
- 使用指针访问数组
- 一维数组传参的本质
- 冒泡排序
- 二级指针
- 指针数组
- 指针数组模拟二维数组
数组名的理解
之前我们在使用指针访问数组内容时,有这样的代码:
int arr[10]={1,2,3,4,5,6,7,8,9,10};
int* p=&arr[0];
这里我们使用&arr[0]的方式拿到了数组第一个元素的地址,但是其实数组名本来就是地址,而且是数组首元素的地址。
我们来做个测试,看数组名到底是不是首元素的地址:

从打印出来的值来看,它们确实是一样的,所以数组名确实是首元素的地址。
那么数组名是首元素地址的话,我们去求地址长度,在32位平台下应该为4个字节(地址的长度与多少位的平台有关)
我们用sizeof计算下地址长度是多少:

这是为什么呢?
数组名就是数组首元素(第一个元素)的地址,但是有两个例外:
sizeof(数组名),sizeof中单独放数组名时,这里的数组名表示整个数组,不是首元素的地址,此时计算的是这整个数组的大小,单位是字节。&数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)
从值的角度来看的话,取整个数组的地址与取首元素的地址打印出来的值一模一样。
这是因为无论是取首元素地址,还是取整个数组的地址,它们的值都是从首元素的地址开始的。
但是我们平时写代码的时候要知道,数组名前+取地址符号是取整个数组的地址。
如果我们想看看它们的区别还是可以看到的,我们给首元素的地址、整个数组分别都+1:


我们发现,前两个地址+1都只跳过了一个整形的大小,而第三个地址+1却跳过了一个数组的大小(40个字节)
所以我们将三个地址打印出来只能看到打印出来的值是一样的,但是类型绝对是不同的,因为int*类型+1跳过的应该是一个整形,而不是40个字节。
除此之外,任何地方使用数组名,数组名都表示首元素的地址。
使用指针访问数组
有了前面知识的支持,再结合数组的特点,我们就可以很方便的使用指针访问数组了。
为什么在访问数组的时候可以使用指针呢?
1.因为数组在内存中是连续存放的,只要是连续存放的,只要找到第一个,就可以顺藤摸瓜找到其他的了。
2.指针±整数的运算,方便我们获得每一个元素的地址
接下来我们写个代码,实现用指针访问数组,给数组的每个元素输入值,再输出值。
注意:
数组就是数组,是一块连续的空间(数组的大小与元素个数和元素类型都有关系)
而指针(变量)就是指针(变量),是一个变量(通常是4/8个字节)
那么它俩之间的联系是什么呢?
数组名是地址,是首元素的地址,可以使用指针来访问数组
拓展:
我们知道arr[i]与*(arr+i)这两种写法是完全等价的,并且*(arr+i)里面的式子是加法,加法是支持交换律的。所以arr[i]==*(arr+i)==*(i+arr)
我们代入代码中看会不会错:

结果也是正确的。
既然这三个等价:arr[i]==*(arr+i)==*(i+arr)
*(arr+i)可以写成arr[i],那么*(i+arr)可不可以写成i[arr]呢?
我们带入代码试试:

我们发现即使是这样程序也没有问题。那么这说明了什么呢?
我们知道[]是个下标引用操作符,既然加号操作符+可以实现:1+2可以写成2+1;那么,arr[i]也就可以写成i[arr]了
提示:这种方式虽然可行,但是不推荐。
因为这样写不利于阅读代码。
一维数组传参的本质
数组我们学过,数组是可以传递给函数的,现在我们讨论一下数组传参的本质。
首先从第一个问题开始:
写个函数实现数组元素的打印,我们之前都是在函数外部计算数组元素的个数:

那我们可以只把数组传给函数,少传一个参数。然后在函数内部求数组的元素个数再打印数组嘛?
此时我们这样写却出现错误,数组里的元素只打印了一个,这是为什么呢?我们进行调试:
- 按F11开始调试,创建数组执行完后打开监视,查看创建的数组有没有问题:

- 发现创建数组没有问题后按F11进入函数内,在监视里输入
arr,10查看数组传参有没有问题:
此时数组的传参也没有问题,我们继续调试。 - 当我们继续往下执行的时候却发现原本期望的值是10,这里
sz却显示的是1
如果sz是1的话,在下面循环中只能循环一次,所以也就只能打印第一个元素的。
此时就找到了问题所在,是sz出问题了。
所以这为什么会算错呢?
我们之前讲过,数组传参有两个例外:sizeof(数组名), &数组名。
只有这两种例外表示的是整个数组,而现在这段代码中的Print(arr)并不算这两种情况,所以此时传的是首元素的地址。
那我们将首元素的地址传过去,Print()函数接收不应该用指针嘛?
这个函数接收的正确写法就应该是int* p这样的指针来接收。
那为什么我们之前用int arr[10]这样数组的形式去接收呢?
因为数组传参的时候,形参的部分是可以写成数组的形式的。对于我们之前初学来说,传的是数组,就用数组来接收,这样讲法对于我们初学接受度很好。
形参的部分虽然可以写成数组的形式,但是本质上还是指针变量(地址)。就相当于这个地方是int* arr
既然Print()不属于那两种例外,所以传的就是个地址,形参也就是个指针变量。
那么下面的sizeof(arr)就不是求一个数组的大小了,而是求一个指针变量的大小:
在x86的环境下,无论什么类型的指针,都是4个字节。
所以数组传参的时候,形参是可以写成数组的形式的,但是本质上还是一个指针变量(地址),下面要求大小的时候
sizeof(arr)求的就不是一整个数组的大小,而是首元素地址的大小。
所以int sz = sizeof(arr) / sizeof(arr[0])是得不到元素个数的
还有一点要说明:
我们说数组传参的时候传的是首元素的地址(假设是0x0012ff40),所以传给函数的地址也是0x0012ff40。
所以我们在这个函数里使用的都是0x0012ff40这个地址
既然实参使用的是0x0012ff40,形参也是使用0x0012ff40,那么实参跟形参使用的数组不就是一样的嘛?
所以我们得到以下结论:
- 数组传参的本质是传递了数组首元素的地址,所以形参使用的数组跟实参使用的数组一定是同一个数组。
- 既然形参使用的数组跟实参使用的数组是同一个数组,所以形参的数组是不会单独再创建数组空间的,形参的数组是可以省略掉数组大小的:


注意:无论形参部分写不写10,都不影响下面int sz = sizeof(arr) / sizeof(arr[0])这个表达式(正确写法时这个表达式一定要放在函数外面!)
接下来我们将这段错误代码改过来:
1.既然数组传的是地址,函数的形参就写成指针
2.求数组元素的表达式放在函数外面
正确代码:

冒泡排序
冒泡排序解决的是排序的问题。
冒泡排序的核心思想就是:两两相邻的元素进行比较。
假设我们这里有一串降序的数字:9 8 7 6 5 4 3 2 1 0
我们要排成升序:0 1 2 3 4 5 6 7 8 9 ,此时该怎么用冒泡排序排成升序呢?


就这样一对一对的比较下去,最后9会到最后:

因为9是最大的一个元素,所以它无论与谁进行比较,都来到最后一位。
这样将9放在最后,我们叫做一趟冒泡排序
所以剩下该解决9前面的数字

所以,一趟冒泡排序解决一个数字。第一趟解决了最大的,第二趟解决了次大的…
那么这个地方有10个元素,要有几趟冒泡排序呢?
9趟。因为前9个数字在进行冒泡排序后,已经在它们应该在的位置上了,最后一个数字自然而然就在它应该在的位置上。
所以是n个元素的时候,我们需要进行n-1趟冒泡排序。
我们开始写代码进行实现:
-
先将元素和排序的函数创建出来

-
当我们把排序函数名字写好之后就是传参了,因为我们要排的是这个数组,所以数组需要传进函数。
并且冒泡排序的趟数得依据元素的个数,而函数内部不能求元素个数,所以得在主函数里面求元素的个数
-
接下里写冒泡排序里的内容
-
写形参:指针接收数组(用数组形式也行),
int sz接收元素个数。
因为这个函数只用排好序就行了,所以返回类型写个void就可以了。
-
因为冒泡排序是一趟解决一个元素,所以首先要考虑趟数

上面我们说过,当有n个元素的时候,我们需要进行n-1趟冒泡排序,所以i<sz-1 -
趟数确定后就思考一趟的排序过程:
一趟排序的过程就是两个相邻元素之间相比较,我们创建一个变量j视为元素下标,使得相邻两元素之间相比较。
-
接下来我们分析:一趟冒泡排序要进行多少对比较。
以上面的例子来说,当我们进行第一趟冒泡排序的时候,待排序的元素有10个,需要进行9对比较
所以代码循环次数可以写成这样,控制9次相邻元素进行比较

但是我们发现:当我们进行第二趟冒泡排序的时候,待排序的元素有9个,需要进行的是8对比较
所以比较次数也与趟数有关:
当第一趟冒泡排序时有10个待排元素,我们要进行9对比较;
当第二趟冒泡排序时有9个待排元素,我们要进行8对比较;
即第三趟冒泡排序时有8个待排元素,我们要进行7对比较…
所以我们将循环次数改为:j<sz-1-i(因为i控制了趟数)

此时当第一趟冒泡排序的时候,就可以进行9对比较;第二趟冒泡排序的时候,就可以进行8对比较了…
-
-
在冒泡排序函数执行完之后,我们写个函数将这个被排完序的数组打印出来:

完整的代码为:
void bubble_sort(int arr[], int sz)
{//趟数int i = 0;for (i = 0; i < sz - 1; i++){//一趟排序的过程int j = 0;for (j = 0; j <sz-1-i ; j++){if (arr[j] > arr[j + 1]){int tmp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = tmp;}}}
}void print_arr(int arr[], int sz)
{int i = 0;for (i = 0; i < sz; i++){printf("%d ",arr[i]);}
}int main()
{int arr[] = {9,8,7,6,5,4,3,2,1,0};//排序int sz = sizeof(arr) / sizeof(arr[0]);//元素个数bubble_sort(arr,sz);//打印print_arr(arr,sz);return 0;
}
打印出的结果:

注意:这段代码是可以优化的。
当需要排序的数组本身是接近有序的情况时:9 0 1 2 3 4 5 6 7 8,此时只需要进行一趟冒泡排序就可以变成:0 1 2 3 4 5 6 7 8 9 
那我们该怎么进行优化呢?
-
我们定义一个变量
flag,在进行每趟冒泡排序之前都假设这趟元素已经有序:
-
如果这趟数组不是有序的,将
flag改为0:
例如9 0 1 2 3 4 5 6 7 8这个数组第一趟冒泡排序时9与0交换了,所以这趟并不是有序的,就将flag改为0,进行下一趟的比较。

-
下一趟全部比较完后发现并没有进入到
if语句中(0 1 2 3 4 5 6 7 8 98次比较全部不符合if中的表达式,没进入if语句中),所以flag还是为1,此时就可以跳出循环,不再进行第3趟、第4趟的比较排序了。

注意:这个break跳的是这个循环,break是在这个循环里的

所以,当任何一对元素交换了,就说明这一趟的元素不是有序的,就得进行下一趟的元素比较、交换。
若是下次没有元素的交换,就说明这一趟的元素就是有序的,不用再进行下一趟了,所以直接跳出循环。
二级指针
我们写段常见的代码:

这就是我们之前用的一级指针。
那么什么是二级指针呢?
我们根据上面这段代码画出图:

既然p也有地址,那么我们就可以通过&p拿到p的地址,然后放进变量pp里。此时pp就存放着一个一级指针变量的地址,我们叫pp为二级指针。


那么pp的类型该怎么写呢?
pp的类型为int**,完整写法:int** pp=&p;
对于这个类型int**我们该怎么去理解呢?
首先我们要知道,int**是二级指针的类型。
所以一级指针与二级指针的类型理解思路是一样的,分两部分理解:
- 最后一个
*说明该变量是指针 - 前面一部分说明该变量指向的对象类型
那么,此时p+1与pp+1各自跳过几个字节呢?
我们知道,指针±整数与指针的类型有关。因为p是整形指针,指向的对象为整形,所以p+1跳过4个字节。
那么pp+1呢?
因为pp指向的是int*类型的变量,也就是指针变量。
所以我们就要看指针变量的大小为多少,就跳过几个字节。有可能是4个字节,也有可能是8个字节。

如果我们想取出pp的地址可以吗?
当然是可以的,此时得写成:int*** ppp=&pp;
同样的:int**说明ppp指向的对象(pp)是int**类型的,最后一个*说明ppp是指针变量。此时ppp就是一个三级指针。
可以一直往下推,但是不建议。
那么二级指针到底是怎么样用的呢?
如果我们要通过pp找到p有什么办法呢?
解引用pp将p的地址打印出来:

*pp——访问pp里存的地址,找到这个地址后拿该地址里的数据(对pp里的地址进行解引用)
我们也将a的地址打印出来,看看*pp的值是不是a的地址

发现值确实一样。
我们通过对二级指针解引用,可以找到一级指针内存的数据,再进行解引用,就可以找到10了.
*pp==p==&a;
//通过对pp里的地址解引用找到p(a的地址)
//对*pp再次解引用:
**pp==*p=10

所以,对二级指针变量两次解引用可以间接的找到10.
指针数组
指针数组是指针还是数组呢?
答案是数组。
我们类比一下:整型数组,是存放整型的数组;字符数组,是存放字符的数组。
所以指针数组,是存放指针的数组。

指针数组的每个元素都是地址,可以指向⼀块区域
那么指针数组有什么用呢?
我们可以用指针数组模拟二维数组。
指针数组模拟二维数组
举例:

当我们写下这样的代码的时候,我们知道,这三个数组各自是一块内存空间,在内存里也并不是连续存放的,可能离得很远。
如果我们想把这三块空间弄成二维数组:将这三个数组分别当成二维数组的第一行、第二行、第三行。
我们该怎么办呢?
因为数组名是首元素的地址,我们将这三个数组首元素的地址放入到一个指针数组arr中,通过访问这个指针数组,再访问到这三个数组。
这样就可以模拟出一个二维数组了:

当我们写上arr[0]的时候,就是访问arr数组中arr1这个元素,而这个元素是arr1数组首元素的地址,所以我们就可以在这个地址的基础上进行+整数,进行arr1数组元素的遍历。
同理,当我们写上arr[1]的时候,就是访问arr数组中arr2这个元素,而这个元素是arr2数组首元素的地址,所以我们也就可以找到arr2数组中的每个元素了…
//可以看作访问第一行所有元素
arr[0][j]; j:0~4//访问第二行所有元素:
arr[1][j]; j:0~4//访问第三行所有元素:
arr[2][j]; j:0~4
这样就实现了指针数组模拟二维数组
因为arr1共有5个元素,首元素地址+0为元素1的地址,首元素+1为元素2的地址…首元素+4就为元素5的地址了,所以整数j的取值范围就为0~4
我们继续写代码:

实现了每个元素的打印。
注意:这种写法并不是真的二维数组,真的二维数组在内存中是连续存放的,而这种写法只是通过地址将三个分散的数组看为三行,再进行打印,这里的arr并不是真的二维数组。
那么既然arr并不是真的二维数组,那么代码中的打印为什么要写成二维数组的形式呢?

因为:
相关文章:
C语言——深入理解指针(2)(数组与指针)
文章目录 数组名的理解使用指针访问数组一维数组传参的本质冒泡排序二级指针指针数组指针数组模拟二维数组 数组名的理解 之前我们在使用指针访问数组内容时,有这样的代码: int arr[10]{1,2,3,4,5,6,7,8,9,10}; int* p&arr[0];这里我们使用&ar…...
Open-WebUI官方部署文档
Github地址:GitHub - open-webui/open-webui: User-friendly AI Interface (Supports Ollama, OpenAI API, ...) 打开 WebUI 👋 如果你是零基础的小白,不知道什么是DeepSeek的话?不知道如何本地化部署,我强烈建议先看…...
爬虫破解网页禁止F12
右击页面显示如下 先点击f12再输入网址,回车后没有加载任何数据 目前的一种解决方法: 先 AltD ,再 CtrlShifti...
vuex 简单使用
vuex 简单使用 示例:管理一个对象状态 假设我们要管理一个用户对象 user,包含 name 和 age 两个属性。 1. 定义 Vuex Store 在 store/index.js 中定义状态、mutations、actions 和 getters: import { createStore } from vuex;const store…...
机器学习_16 朴素贝叶斯知识点总结
朴素贝叶斯(Naive Bayes)是一种基于贝叶斯定理的概率分类算法,广泛应用于文本分类、垃圾邮件检测和情感分析等领域。它通过计算后验概率来进行分类,核心假设是特征之间相互独立。今天,我们就来深入探讨朴素贝叶斯的原理…...
Xshell连接虚拟机ubuntu,报错(port 22): Connection failed.
Connecting to 192.168.37.131:22... Could not connect to 192.168.37.131 (port 22): Connection failed. 虚拟机ubuntu 可以ping通,但就是连接不上。 先后排查了, 1. 网络适配器是否被禁用 2.设置虚拟机网络适配器的网络连接模式为桥接模式…...
浏览器报错:无法访问此网站 无法找到xxx.xxx.net的DNS地址。正在诊断该问题。尝试运行Windows网络诊断。DNS_PROBE_STARTED
🤟致敬读者 🟩感谢阅读🟦希望我的文章能帮到您🟪如有兴趣可点关注了解更多内容 📘博主信息 点击标题👆有惊喜 📃文章前言 🔷文章均为学习和工作中整理的笔记,分享记录…...
2024年国赛高教杯数学建模C题农作物的种植策略解题全过程文档及程序
2024年国赛高教杯数学建模 C题 农作物的种植策略 原题再现 根据乡村的实际情况,充分利用有限的耕地资源,因地制宜,发展有机种植产业,对乡村经济的可持续发展具有重要的现实意义。选择适宜的农作物,优化种植策略&…...
React中如何处理高阶组件中的错误
在 React 高阶组件中处理错误是确保应用程序健壮性和稳定性的重要环节。以下是一些处理高阶组件中错误的常见方法: 1. 捕获渲染时的错误 在高阶组件中,渲染过程可能会因为各种原因(如 props 数据格式错误、组件内部逻辑异常等)抛…...
CentOS/RHEL如何更换国内Yum源
在国内使用CentOS或RHEL系统时,默认的Yum源是国外的,这可能导致软件包的下载速度慢,甚至出现连接超时的问题。为了解决这个问题,我们可以将Yum源切换到国内的镜像源,从而大大提高软件包的下载速度和稳定性。 本文将详…...
linux 替换jar包中的文件
在 Linux 系统中替换 JAR 文件中的文件,一般可以使用jar命令来完成,以下是具体步骤8: 查找目标文件在 JAR 包中的路径:使用jar tvf命令可以列出 JAR 包中的所有文件,再通过grep命令来过滤出要替换的目标文件。例如&am…...
如何系统成为高级Qt工程师?
要系统性地成为高级Qt工程师,需要从基础到进阶逐步构建知识体系,并结合实战经验、源码分析和架构设计能力的提升。以下是分阶段的系统性学习路径和建议: 一、夯实基础阶段 C++深度掌握 精通C++11/14/17特性(智能指针、lambda、移动语义等)理解面向对象设计、设计模式(如观…...
A9. Jenkins Pipeline自动化构建,飞书通知
怎么收集服务部署信息?【前置】首先Python如何操作JSON数据如何记录部署信息,什么时机统计?如何下发某一服务统计信息 ?那么怎么创建飞书通知机器人呢?编写飞书通知脚本总结下面我们接着上一篇文章《A8. Jenkins Pipeline自动化部署过程,多模块远程服务协调实战》继续往下…...
firefox升级后如何恢复收藏夹和密码的问题
手贱,无聊,看到Firefox提示说再不升级就不能使用了,结果就信了; 升级完之后,傻眼了,收藏夹无法导入,密码全没了 新版的Firefox采用snap方式安装,所以安装路径是在snap下面的&#…...
维护ceph集群
1. set: 设置标志位 # ceph osd set <flag_name> # ceph osd set noout # ceph osd set nodown # ceph osd set norecover 2. unset: 清除标志位 # ceph osd unset <flag_name> # ceph osd unset noout # ceph osd unset nodown # ceph osd unset norecover 3. 标志…...
亲测!我是如何用 Anything LLM 等搭建 AI 智能知识库的
以下是本地部署Anything LLMOllamaDeepSeek R1打造AI智能知识库的教程: 安装Ollama 下载Ollama:浏览器进入ollama.com主页,点击页面右上角或中间下端黑底的“Download”。选择对应的系统图标,如Windows用户点击“Download for W…...
汽车零部件开发应该具备哪些编程思维?
目录 1、功能安全思维 2、实时性与确定性思维 3、可靠性和冗余思维 4、硬件软件协同思维 5、CAN总线通信思维 6、故障诊断和自诊断思维 7、功耗优化思维 8、软件更新和版本管理思维 9、用户体验与安全性思维 汽车零部件开发中,嵌入式软件在车辆系统中的作用…...
利用 OpenCV 进行棋盘检测与透视变换
利用 OpenCV 进行棋盘检测与透视变换 1. 引言 在计算机视觉领域,棋盘检测与透视变换是一个常见的任务,广泛应用于 摄像机标定、文档扫描、增强现实(AR) 等场景。本篇文章将详细介绍如何使用 OpenCV 进行 棋盘检测,并…...
DeepMind发布Matryoshka(套娃)量化:利用嵌套表示实现多精度LLM的低比特深度学习
本文将介绍 Google DeepMind 提出的 Matryoshka 量化技术,该技术通过从单个大型语言模型 (LLM) 实现多精度模型部署,从而革新深度学习。我们将深入研究这项创新技术如何提高 LLM 的效率和准确性。 随着深度学习模型在规模和复杂度上持续增长,…...
DeepSeek01-本地部署大模型
一、ollama简介: 什么是 Ollama? Ollama 是一个用于本地部署和管理大模型的工具。它提供了一个简单的命令行界面, 使得用户可以轻松地下载、运行和管理各种大模型。Ollama 支持多种模型格式, 并且可以与现有的深度学习框架&#x…...
Java-数据结构-(HashMap HashSet)
一、Tree和Hash的区别 在上一篇文章中,我们讲到了"TreeMap"和"TreeSet",但当我们刷题的时候却会发现,实际应用Map和Set时,却常常都只会用"HashMap"和"HashSet",这是为什么呢…...
举个栗子:浅显易懂的理解Transformer 模型
用一个简单的比喻来解释 Transformer 模型,让你轻松理解它的工作原理。 Transformer 的比喻:一个高效的翻译团队 想象一下,Transformer 模型就像一个高效的翻译团队,它的任务是把一段英文翻译成中文。这个团队由两部分组成&#…...
el-table 结合 slot 具名插槽遍历封装列表模板
基础效果 要实现以上效果,可对 el-table 进行封装,将列配置视为数组,循环 el-table-column 标签模板组件 <div class"tableSlot"><el-table :data"dataList" border><el-table-columnv-for"(item, …...
游戏引擎学习第108天
仓库:https://gitee.com/mrxiao_com/2d_game_2 看一下我们现在的进展 今天的工作重点是处理游戏中的Z轴问题,特别是如何在不同的层级之间进行移动,并确保Z轴的处理方式与真实世界中的透视效果一致。当前,游戏中的Z轴运动存在问题࿰…...
遵循规则:利用大语言模型进行视频异常检测的推理
文章目录 速览摘要01 引言02 相关工作视频异常检测大语言模型 03 归纳3.1 视觉感知3.2 规则生成Normal and Anomaly (正常与异常)Abstract and Concrete (抽象与具体)Human and Environment (人类与环境) 3…...
网页制作01-html,css,javascript初认识のhtml的基本标记
一、 Html简介 英文全称是 hyper text markup language,超文本标记语言,是全球广域网上描述网页内容和外观的标准. Html作为一款标记语言,本身不能显示在浏览器中.标记语言经过浏览器的解释和编译,才能正确地反映html标记语言的内容. 1.html 的基本标记 1)头部标…...
vue 判断字符串开头是http或者https
在 Vue 中判断字符串是否以 http 或 https 开头,可以通过以下步骤实现: 方法一:使用 startsWith() 方法 // 在 Vue 组件的方法或计算属性中 isExternalLink(url) {return url?.startsWith(http://) || url?.startsWith(https://); }方法二…...
linux常用命令大全(包括抓包、网络检测、路由等,做项目一点点总结而来!)
文章目录 常用命令**apt相关****ls**:**cd****cp****ls -l | grep ssh**:会列出当前目录中包含 “ssh” 的文件或目录的详细信息。**系统资源**linux路由相关抓包工具和命令tcpdumpwiresharktshark iperf 常用命令 通过上下方向键 ↑ ↓ 来调取过往执行过…...
HarmonyOS组件之Tabs
Tabs 1.1概念 Tabs 视图切换容器,通过相适应的页签进行视图页面的切换的容器组件每一个页签对应一个内容视图Tabs拥有一种唯一的子集元素TabContent 1.2子组件 不支持自定义组件为子组件,仅可包含子组件TabContent,以及渲染控制类型 if/e…...
Linux学习笔记之虚拟地址空间
1.示例引入 运行如下代码那么运行结果如下图。 #include<stdio.h> #include<unistd.h>int main() {pid_t id fork();if(id-1){printf("创建进程错误!\n");return 1;}int size0;if(id0){//子进程while(1){printf("我是子进程,…...
