初识C语言指针(3)

news2024/9/22 7:23:42

目录

1. 数组名的理解

2. 使⽤指针访问数组

3. ⼀维数组传参的本质

4. 冒泡排序 

5. 二级指针

6. 指针数组

7. 指针数组模拟⼆维数组 

结语

 


1. 数组名的理解

对于数组名想必大家并不陌生,数组名就是该数组首元素的地址,设想有一个arr 数组。我们一起来观察一下,arr、&arr、&arr[0] 的之间的关系吧

我们发现它们3个打印出来的结果貌似都是数组首元素的地址,别急我们将它们分别+1看看结果:

 

可以发现 arr+1 和 &arr[0]+1都是加了4个字节,而&arr则是加了40个字节,而40个字节大小是arr数组所有元素相加的大小,所以&arr 取出来的是整个数组的地址。但是arr是数组⾸元素的地址,那sizeof(arr)输出应该的应该是4或者8才对。那为什么sizeof(arr)会输出40呢?

 其实数组名就是数组⾸元素(第⼀个元素)的地址是对的,但是有两个例外:

1.sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表⽰整个数组,计算的是整个数组的⼤⼩, 单位是字节

2. &数组名,这⾥的数组名表⽰整个数组,取出的是整个数组的地址(整个数组的地址和数组⾸元素的地址是有区别的)

除此之外,任何地⽅使⽤数组名,数组名都表⽰⾸元素的地址。

2. 使⽤指针访问数组

通常情况下,我们都是通过数组的下标进行访问的:

既然arr表示首元素地址,那么将arr赋给p此时的p其实就是arr,那么我们是不是可以写成 p[ i ] 呢?

我们知道此时的p就是 arr数组首元素的地址,那么p+1就是arr数组中下标为1的元素的地址,所以*(p+1)就是下标为1的元素,所以我们还可以写成这样:

既然p等于arr ,所以还可以写成*(arr+i)的形式:

 其实arr[ i ]这种写法,在编译器执行的时候,也会转换成*(arr+i)的形式执行,所以arr[ i ]和*(arr+i)是完全等价的,同样p等于arr 所以p[ i ]与*(p+i)也是完全等价的。以上就是通过指针访问数组的几种形式。

3. ⼀维数组传参的本质

数组名是数组⾸元素的地址;那么在数组传参 的时候,传递的是数组名,也就是说本质上数组传参传递的是数组⾸元素的地址,例如:

此时函数的形参部分接收到的应该是数组首元素的地址,所以在test函数中 使用sizeof计算的自然是数组第一个元素的大小,数组第一个元素大小除以数组第一个元素大小,得到的自然就是1,所以在函数内部是没办法求的数组元素个数的。

总结:

1.数组传参传递的是数组首元素的地址

2.函数形参部分不会重新创建数组,所以定义的时候不需要写数组大小

3.函数形参部分实际上应该使用指针变量来接收实参传过来的地址

4.函数形参部分写成数组的方式,主要是为了方便理解,方便使用,本质上要写成指针变量的形式

4. 冒泡排序 

对数据进行排序的方法有很多,我们讲讲冒泡排序:冒泡排序是一种简单的排序算法,它重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。

例如我们要将一组数据从小到大排序

动图演示:

 假设我们要将一组由10个元素组成的数组从小到大排序:

void paixu(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		int f = 1;//默认排好了
		for (int j = 0; j < sz - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int t = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = t;
				f = 0;
			}
		}
		if (f == 1)
		{
			break;
		//如果没有交换位置,说明已经排好了,跳出循环
		}
	}
}
void print(int arr[], int sz)
{
	for (int i = 0; i < sz; i++)
	{
		printf("%d ", arr[i]);
	}
	printf("\n");
}
int main()
{
	int arr[10] = { 4,8,1,6,7,2,9,3,5,10 };
	int sz = sizeof(arr) / sizeof(arr[0]);
	printf("排序前:");
	print(arr, sz);
	paixu(arr, sz);//排序
	printf("排序后:");
	print(arr, sz);
	return 0;
}

 

冒泡排序就是通过两两相比进行位置的交换,这里就是arr[ j ]和arr[ j+1 ]进行比较, 所以这里的循环条件应该写成 j <sz-1 (10-1),这样 j+1的时候下标就不会越界,然后结合动图我们可以发现每一次的排序都会将最大值放在最后,所以就不需要再次对最大值进行比较,所以我们就可以写成 ( j <sz-1-i ),当我们经过每一次的排序得到最大值,如果有一次排序发现没有交换过位置,说明已经排序成功了,这时候就可以写个判断跳出循环,这样就减少了运行次数,减少了多余的操作。

5. 二级指针

指针变量也是变量,是变量就有地址,所以二级指针就是用来存放一级指针变量的地址。

       pa存放的是a的地址,所以*pa=a=10 ,而ppa存放的是pa的地址,所以*ppa=pa,那么 **pa=*pa=a=10;这就是二级指针解引用的结果。

6. 指针数组

我们知道整型数组,是存放整型的数组,字符数组是存放字符的数组。 那指针数组呢?自然就是存放指针(地址)的数组,指针数组的每个元素是地址,⼜可以指向⼀块区域。

可以看见数值中存放的是a、b、c的地址,那么我们也可以通过解引用找到它们的值:

7. 指针数组模拟⼆维数组 

我们知道二维数组的元素是一维数组,那假设有一个指针数组,指针数组中存放着3个一维数组首元素的地址,我们是否可以通过指针访问到3个一维数组中的每一个元素呢?

这时我们发现通过数组的下标竟然也可以访问,这是为什么呢?

arr数组存放的是3个一维数组的首元素地址, arr[0]其实就是arr1的首元素的地址,那么我们想访问arr1中的数组只需要对(arr[0]+j)进行解引用即可,上图中的arr[ i ][ j ]在编译器执行的时候会转换成 *(arr[ i ]+j)的形式,所以通过下标的方式还是指针的方式都能够访问到数组中的元素。

结语

以上就是本章的全部内容,细心的小伙伴一定发现了本章的内容是关于数组与指针之间的联系,相信大家看完后都有所收获,希望大家能够明白数组与指针之间的联系以及用法,后续会持续更新指针的内容,感谢大家的观看!!!

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

文本是否换行显示

多行文本 1、white-space: pre-wrap; 保留连续的空白符。在遇到换行符或 <br> 元素时&#xff0c;或者根据填充行框盒子的需要换行。 2、word-break: break-word; 如果单词太长而无法在当前行容纳&#xff0c;浏览器可以尝试在单词内部进行断行&#xff0c;以避免内容…

轻松获得ADSL代理服务

ADSL 代理服务接入常见问答 在当今激烈的网络爬虫与反爬虫斗争中&#xff0c;各大网站和应用程序采取的风险管理手段愈加严格&#xff0c;其中最常见的一种措施是 IP 封禁。 为了有效应对 IP 封禁带来的挑战&#xff0c;设置代理服务成为一种非常有效的解决方案。配置完代理后…

数论之高斯消元

高斯消元&#xff1a; 前置知识&#xff1a; 高斯消元五步骤法 枚举每一列c 找到绝对值最大的一行 将该行换到最上面&#xff08;第r行&#xff09; 将该行的第c列数字变为1 把该行下面的第c列数字全部变为0 代回求解 #include <bits/stdc.h>using namespace std;…

Linux LVM 详解

Linux LVM 详解 1. 简介 参考链接&#xff1a; https://blog.csdn.net/qq_35745940/article/details/119054949 https://blog.csdn.net/FP202530/article/details/125140176 &#x1f449; LVM&#xff08;Logical Volume Manager&#xff09;逻辑卷管理 是在硬盘分区和文件系…

面向对象02:构造器详解

本节内容视频链接&#xff1a;面向对象05&#xff1a;构造器详解_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV12J41137hu?p64&vd_sourceb5775c3a4ea16a5306db9c7c1c1486b5 构造器&#xff08;‌Constructor&#xff09;‌是一种特殊的方法&#xff0c;‌用于初始…

解决Intel-12代13代14代大小核调用导致VMware虚拟机性能低

0x01 设备信息 近期入手的是一台2023款 y9000p 游戏本&#xff0c;CPU为13500h 显卡为RTX4060。 0x02 VMware虚拟机遇到的性能问题 尤其是windows虚机明显感觉性能非常差&#xff0c;开几个网页都很卡。 我一度怀疑是CPU i5性能差&#xff0c;还没我的轻薄本运行速度快&…

jmeter中CSV 数据文件设置用例

1、CSV数据文件的基础使用 线程组->添加->配置远近->CSV数据文件设置 2、多条用例运行CSV数据文件 由于我的csv请求的json数据有“&#xff0c;”所以我这边 分隔符选择了*号 写了两行需要测试的用例&#xff0c;需要添加一个“循环控制器” 线程组->添加-&g…

省时又省力!2024年最新录屏软件快捷键大放送

录屏工具可以帮我们录制教学视频、游戏精彩瞬间等内容。很多时候录制的过程瞬息万变&#xff0c;如果合理使用录屏快捷键就会极大的缓解我们录制时候的慌乱。今天&#xff0c;就让我们一起探索那些“大家都在用的录屏软件快捷键”&#xff0c;看看它们是如何让我们的录制工作变…

centos7 xtrabackup mysql(8)压缩 全量备份 还原(4)

centos7 xtrabackup mysql&#xff08;8&#xff09;压缩 全量备份 还原&#xff08;4&#xff09; 查看版本&#xff1a; xtrabackup --version qpress --help 主机端 mysql -u root -p 1234aA~1 use company_pro; insert into employee(name) value (‘20240823_1401’);…

2024.8.23

130124202408231008 DATE #:20240823 ITEM #:DOC WEEK #:FRIDAY DAIL #:捌月二十 TAGS < BGM "Forest Mixtape&#xff08;Tsuki)" > < theme oi-graph theory Eulerian > < [NULL] > < [空] > < [空] >冰岛的温柔是克莱因蓝再加点…

使用nfs搭建文件共享系统,以及windows环境如何访问linux系统中的文件共享目录

31、简介 在一些场景中&#xff0c;我们需要多台机器进行磁盘文件共享&#xff0c;集群中如果有linux机器&#xff0c;也有windows机器&#xff0c;如何设置进行文件共享&#xff0c;本文将详细说明。 注&#xff1a;本文linux系统使用的是 centos7&#xff0c;windows使用的是…

【Qt】常见控件 —— QWidget

文章目录 QWidget 的基本介绍QWidget 的 enable 属性QWidget 的 geometry属性 QWidget 的基本介绍 Qt 中 的 各种控件 都继承自 QWidget类 在 Qt designer 右侧 就显示出 QWidget的各种属性 并且也可以直接进行编辑 QWidget 的 enable 属性 enable 描述一个控件是否处于可用 …

前端面试题整理-webpack

实现前端模块化&#xff0c;将多个 js&#xff0c;打包成一个 bundle.js (其他类型文件交由各自的 loader 处理) 1. webpack 了解吗&#xff1f;大概介绍一下 一种打包工具&#xff0c;实现前端模块化&#xff0c;将多个 js&#xff0c;打包成一个 bundle.js (其他类型文件交…

Linux中查看端口被哪个进程占用、进程调用的配置文件、目录,address already in use端口被占用杀死并释放端口

1.查看被占用的端口的进程&#xff08;netstat和ss是一样的&#xff0c;较新的系统推荐ss&#xff09;: netstat -antulp | grep 端口号ss -antulp | grep :端口号lsof -i | grep 端口号2. 通过上面的命令就可以列出&#xff0c;这个端口被哪些应用程序所占用&#xff0c;然后找…

Java设计模式之策略模式详细讲解和案例示范

Java设计模式之策略模式详细讲解和案例示范 在软件开发中&#xff0c;策略模式是一种常见且非常有用的设计模式。它允许定义一系列算法&#xff0c;将它们一个个封装起来&#xff0c;并且使它们可以互相替换。策略模式让算法可以独立于使用它们的客户端而变化。本篇文章将详细…

VScode的python虚拟环境

1 创建虚拟环境&#xff08;venv&#xff09; 在VSCode中打开项目文件夹&#xff0c;键盘按住快捷键ctrl shift p&#xff0c;打开命令面板&#xff0c;输入python:创建环境 选择venv&#xff0c;输入解释器路径&#xff0c;此时左侧文件夹内会出现一个.venv文件夹 2 激活虚拟…

未来已来:探索机器学习如何重塑人工智能的未来方向

引言&#xff1a;机器学习室实现人工智能的关键技术手段&#xff0c;应用领域持续延伸 机器学习是人工智能的一个重要分支&#xff0c;主要研究如何让计算机系统通过数据学习并做出决策或预测&#xff0c;而不需要明确的编程。简单来说&#xff0c;就是让计算机利用经验来提高性…

C# 如何实现接口事件:详解与示例

文章目录 实现接口事件的步骤示例&#xff1a;实现接口事件1. 定义接口事件2. 实现接口事件3. 订阅和触发事件4. 使用示例 总结 在C#中&#xff0c;接口&#xff08;interface&#xff09;是一种定义类必须实现的方法和属性的抽象类型。除了方法和属性&#xff0c;接口还可以包…

浅谈红队攻防之道-CobaltStrike钓鱼攻击集锦

打个比方&#xff0c;一片大地上&#xff0c;躺着一群沉睡的人&#xff0c;远处就是火山&#xff0c;马上就要爆发了&#xff0c;你就像个闹钟&#xff0c;面对这些沉睡的人&#xff0c;你想把他们叫醒。 你持续不断地响着&#xff0c;有的睡得浅的人&#xff0c;被你叫醒了&am…

区块链基础通识(1)——分布式系统的共识问题

分布式系统 我们最初了解区块链的时候&#xff0c;很多人会形容这个区块链是一个“分布式的不可篡改账本”&#xff0c;这是一个很形象的说法&#xff0c;但是我认为更为准确的形容是“所有节点共同维护的状态机”。为什么分布式和区块链不能划等号呢&#xff1f; 两种常见的…