C语言(指针)4

                 Hi~!这里是奋斗的小羊,很荣幸各位能阅读我的文章,诚请评论指点,关注+收藏,欢迎欢迎~~     

                                💥个人主页:小羊在奋斗

                                💥所属专栏:C语言   

        本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为同样是初学者的学友展示一些我的学习过程及心得。文笔、排版拙劣,望见谅。 

一、指针与数组

        1.数组名

        通过前面的学习我们知道,数组名就是数组首元素的地址,但是看到下面的代码你会不会怀疑这句话呢?

        按道理说数组名是数组首元素的地址,那 sizeof(arr)求出来应该是4个字节的大小,这里为什么是40个字节的大小呢?

        其实,我们说数组名就是数组首元素的地址在大多数情况下并没有错,只是有两个例外。

        (1)sizeof(数组名):这里的数组名表示的是整个数组,计算的是整个数组的大小,单位是字节;

        (2)&数组名:这里的数组名表示的也是整个数组,取出的是整个数组的地址。 

            除此之外,数组名表示的都是数组首元素的地址。 

        看到上面 “取出的是整个数组的地址” 这句话,有些小伙伴可能又有疑惑了,因为他们记得我在之前的文章中说过,不管内存地址多大, “&” 操作符取出的只是内存单元地址最小的那个,那么不管是数组首元素的地址,还是整个数组的地址不是都一样吗?那为什么还要区分呢?

        如果你并没有这个疑惑,可能是你学的非常扎实,我们一起继续努力;也可能是你学的还不太扎实,或者没有好好看我之前的文章,罚你去看 —> C语言(指针)1 。

        我们在之前的文章中说过,指针的类型决定了指针的差异、决定了在对指针进行解引用时的权限、指针 +- 整数的结果取决于指针的类型等。我们还说过,地址就是指针,指针就是地址,当我们对数组首元素的地址和整个数组的地址进行一些操作时,你还觉得它们没什么区别吗?

        ( 我们每次打印得到的地址都不一样,不必在意 )。 

        可以看到,对数组首元素的地址+1增大了4个字节,对整个数组的地址+1增大了40个字节(其中地址是16进制表示),这一点相信看过我之前文章的小伙伴都已经非常清楚了,就不再赘述了。所以说,虽然数组首元素的地址和整个数组的地址取出来是一样的,但还是有很大的差别的。

        2.使用指针访问数组

        其实在之前的文章中我们已经多次的使用了指针来访问数组,这里只做一些补充。

        上面的几种输入方式都是可行的,但是你不能写成下面这种:

        上面代码的问题是,当输入操作结束后指针变量p已经指向数组内最后一个元素,如果你还想要通过指针自加的方式打印数组,就需要重新让指针变量p指针数组首元素。这种写法不推荐,还是写成之前的那几种形式更好一些。

        3. 一维数组传参的本质

        之前已经说过,数组传参的时候实参直接写数组名,传递的是数组首元素的地址,形参可以写数组的形式,也可以写指针的形式。来看下面的代码:

        上面sz1和sz2的值打印出来是一样的吗?如果不一样sz1和sz2分别等于多少?

        打印出来sz1 = 10,sz2 = 1。 

        对于sz1, sizeof(arr)中的 “arr” 表示的是整个数组的地址,所以sizeof(arr)求的是整个数组的大小,单位是字节,sizeof(arr[0])求的是数组首元素的大小,所以相除的结果应该就是数组内元素的个数;对于sz2,因为前面说过数组传参的时候传递的是数组首元素的地址,所以自定义函数fun()形参接收的时候自然只能得到数组首元素的地址,那么sizeof(arr)中的 “arr” 表示的只是数组首元素的地址,求出的就只是数组首元素的大小,sizeof(arr[0])求出的也是数组首元素的大小,所以相除的结果就为1。

        有没有对上面代码形参的部分写的 int arr [ ] 有疑惑呢,并不是我们之前写过的 int *arr,按道理来说数组传参传过来的是地址,应该用指针来接收,但是依旧能正常运行。所以我想说的是,arr[ ]本质上也是指针,arr[i] == *(arr + i)。其中括号内写不写数组的长度都是无所谓的,因为它只能接收首元素的地址。

        那我们想在自定义函数中使用数组内元素的个数这个值怎么办呢?很简单,将这个值作为函数参数传过去就行。

        总结:(1)不能看到sizeof(arr)就认定了arr表示的是整个数组的地址,还要看它是不是函数的形参;

                   (2)在用上面的方法求数组内元素个数的时候,最好紧跟在数组的定义后面写;

                   (3) 形参即使写成数组的形式,本质上也是一个指针变量;

                   (4)在自定义函数中使用数组内元素个数这个值需要在函数调用的时候作为函数参数传过去。

        4.冒泡排序

        学了上面的内容,我们就可以用数组和指针的知识来实现一下冒泡排序。我们这里写升序。

        首先,我们先简单地介绍一下冒泡排序是怎么一回事,详细的解释这里就不赘述了,不了解的同学还请查看别的资料。冒泡排序就是重复地遍历要排序的一组数,比较相邻的元素,并交换它们的位置,直到整个列表都是按照从小到大(或从大到小)的顺序排列,如果有N个元素重复的次数就是N - 1次。

        具体实现如下:

#include <stdio.h>

void bubble_sort(int arr[], int n)
{
	int i = 0; 
	int j = 0;
	int num = 0;
	printf("正序:");
	for (i = 0; i < n - 1; i++)//共n - 1趟
	{
		for (j = 0; j < n - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				num = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = num;
			}
		}
	}
}

int main()
{
	//定义一个数组存放待排序的n个数
	int arr[100] = { 0 };
	int i = 0;
	int n = 0;

	while (scanf("%d", &arr[n++]), arr[n - 1] != -1);//以-1为输入结束标志
	n--;
	//冒泡排序函数
	bubble_sort(arr, n);
	for (i = 0; i < n; i++)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}

        实验结果也没问题: 

        

        但上面的代码效率还不够高,还能再优化一下。请你思考一个问题,如果当某一趟前后两个数两两相互比较过后,并没有发生交换,这时候整个数组中的元素是不是已经有序了?答案是的。那按照上面的代码即使已经有序了还要把每一趟都判断一遍才能结束,做了很过无用功。

        某一趟没有发生交换,就说明这一趟并没有满足 if 判断表达式的情况,那我们就可以在 if 分支的外面和里面设定一个标志,当不满足某一条件是,说明并没有进入到 if 分支内,这时候就可以确定这组数已经有序,然后跳出循环结束任务。

#include <stdio.h>

void bubble_sort(int arr[], int n)
{
	int i = 0; 
	int j = 0;
	int num = 0;
	printf("正序:");
	for (i = 0; i < n - 1; i++)//共n - 1趟
	{
		int flag = 1;//假设这组数本来就是有序的
		for (j = 0; j < n - 1 - i; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				flag = 0;//还没有有序的时候改变标志
				num = arr[j];
				arr[j] = arr[j + 1];
				arr[j + 1] = num;
			}
		}
		if (1 == flag)//如果确实有序就跳出循环
		{
			break;
		}
	}
}

int main()
{
	//定义一个数组存放待排序的n个数
	int arr[100] = { 0 };
	int i = 0;
	int n = 0;

	while (scanf("%d", &arr[n++]), arr[n - 1] != -1);//以-1为输入结束标志
	n--;
	//冒泡排序函数
	bubble_sort(arr, n);
	for (i = 0; i < n; i++)
	{
		printf("%d ", *(arr + i));
	}
	return 0;
}

        如果一组待排序的数是最乱的情况,那上面的代码与之前的一样;如果一组待排序的数已经基本有序,那上面的代码效率更高。

        5.二级指针

        前面不止一次说过,指针变量也是变量,既然是变量就会有地址,普通变量的地址存放在指针变量中,那指针变量的地址存放到哪里呢?接下来就介绍二级指针。

        

        相信通过之前一级指针变量的学习,二级指针对我们来说简直易如反掌,这里就不再过多赘述了。另外三级指针也是这样的用法,但更高级的指针基本用不到。

         二级指针的用法也是类似一级指针的用法:

        ( **ppa == *pa == a )这就像我们玩的套娃,你想拿到最小的那个就一层一层的去找。

        按照前面的内容,一级指针和一维数组有着密切的联系,那二级指针和二维数组有没有联系呢?没有。 

        6.指针数组

        看到这个名字你有没有疑惑,指针数组到底是指针还是数组?我们知道,整型数组是存放整型元素的数组,字符数组是存放字符元素的数组,那同样的指针数组就是存放指针的数组了,其中元素的类型是指针类型。 

        为什么要有指针数组呢?原因和整型数组及其他数组一样,当我们想创建多个相同类型的变量的时候一个一个去创建很繁琐,于是就出现了相应类型的数组,那指针数组的出现也是一样。

        但我们需要创建多个指针变量的时候,指针数组就为我们提供了比较简洁的方法,当然和其他数组一样指针数组也可以遍历打印出来:

         需要注意的是此时数组里存的是地址,需要用解引用操作符 “ * ”。

        7.指针数组来模拟二维数组
         

        上面虽然我们没有定义二维数组,但我们用指针数组的方法模拟实现了二维数组。

        上面代码的执行细节是,我们首先对指针数组arr解引用找到对应下标的元素,其中元素也是地址,那我们再对这个地址解引用就能得到对应下标的元素,此时的元素就是arr1、arr2、arr3三个数组中存的整型元素。 

        如果觉得我的文章还不错,请点赞、收藏 + 关注支持一下,我会持续更新更好的文章。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

瑞的创作纪念日(128天)

&#x1f64a; 前言&#xff1a;我是阿瑞&#xff0c;一个热爱技术、喜欢教学、对编程充满热情、痴迷于代码世界、喜欢研读源码、尝试自研开发框架的探索者。今天&#xff0c;与大家分享一个特别的纪念日——我的 CSDN 技术博客创作第 128 天的纪念日 机缘 我接触 CSDN 是因为 …

零基础HTML教程(32)--HTML5语义化标签

文章目录 1. div时代2. div的缺点3. 语义化标签4. 语义化标签有哪些5. 实战演练6. 小结 1. div时代 我是2009年开始学习网页开发的&#xff0c;那时候HTML里面到处是div。 这么说吧&#xff0c;那时候div就是网页的骨架&#xff0c;支撑着网页的主结构。 2. div的缺点 div作…

硬件 - TL431计算

文章目录 1 . 概要2 . TL431内部3 . TL431应用电路4 . TL431计算5 . 小结 【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 1 . 概要 1 . TL431常用于通过外围电阻R1,R2设置输出一个目标电压 2 . TL431内部 3 . TL431应用电路 1 . R1 1K&#xf…

Mac IDEA 自动补全mybatis sql语句

导航 Mac IDEA 自动补全mybatis sql语句一、点击IDEA 右侧Database选项二、选择添加对应数据库三、输入数据库信息和方案四、输入数据库信息和方案五、成功 Mac IDEA 自动补全mybatis sql语句 背景&#xff1a; 想在Mapper中&#xff0c;能够实现自动检索数据库表和对应的字段…

40道 Nginx 高频面试题

Nginx 是一款轻量级的 Web 服务器、反向代理服务器&#xff0c;由于它的内存占用少&#xff0c;启动极快&#xff0c;高并发能力强&#xff0c;在互联网项目中广泛应用。那么关于 Nginx 的核心面试题有哪些呢&#xff1f;今天给大家整理了40道Nginx 高频面试题&#xff0c;最近…

ITMS-91053: Missing API declaration

1. 添加PrivacyInfo.xcprivacy File → New → File → App Privacy 2. 格式 3. 已知对应关系 NSPrivacyAccessedAPICategoryFileTimestamp 3B52.1: Files provided to app by user, per documentation&#xff1a;File Timestamp NSPrivacyAccessedAPICategoryDiskSpace …

[机器学习-04] Scikit-Learn机器学习工具包进阶指南:集群化与校准功能实战【2024最新】

&#x1f3a9; 欢迎来到技术探索的奇幻世界&#x1f468;‍&#x1f4bb; &#x1f4dc; 个人主页&#xff1a;一伦明悦-CSDN博客 ✍&#x1f3fb; 作者简介&#xff1a; C软件开发、Python机器学习爱好者 &#x1f5e3;️ 互动与支持&#xff1a;&#x1f4ac;评论 &…

人类将会永生?谷歌 DeepMind重磅发布Alphafold 3 ——天花板级别的AI系统

当地时间 5 月 8 日&#xff0c;顶级科学期刊《Nature》发表了一份重磅研究论文。谷歌 DeepMind 发布了其生物学预测工具 AlphaFold 的最新版本——AlphaFold 3。 这个革命性的新模型&#xff0c;能以前所未有的精度预测所有生命分子的结构和相互作用。作为一个以整体方式计算…

如何在线网页浏览obj格式3D模型?

OBJ文件是一种3D模型格式&#xff0c;目前几乎大部分知名的3D软件都支持OBJ文件的读写&#xff0c;但是想要在网页在线查看obj文件&#xff0c;要怎样实现呢&#xff1f; 1、如何在线浏览obj格式模型&#xff1f; 其实只要通过51建模网&#xff0c;直接将obj格式的3D模型上传…

【数据结构】二叉树(Binary Tree)

文章目录 一、树的概念及结构二、二叉树的概念及结构1.二叉树的概念2.特殊的二叉树3.二叉树的性质 三、二叉树的存储顺序存储链式存储 四、二叉树的实现1.创建二叉树2.二叉树的遍历前序遍历中序遍历后序遍历层序遍历根据遍历顺序创建二叉树 3.二叉树的基本操作1.总结点个数2.二…

Vulnhub项目:ICA: 1

1、靶机介绍 靶机地址&#xff1a;ICA: 1 ~ VulnHub 2、渗透过程 首先&#xff0c;部署好靶机后&#xff0c;进行探测&#xff0c;发现靶机ip和本机ip&#xff0c;靶机ip156&#xff0c;本机ip146。 然后查看靶机ip有哪些端口&#xff0c;nmap一下。 出现22、80、3306端口&a…

使用Selenium破解滑动验证码的原理及解决思路

1、获取页面元素信息&#xff1a; 使用Selenium打开目标网页&#xff0c;并通过相关方法获取滑块、背景图等元素的位置和属性信息。可以使用Selenium提供的定位方法&#xff08;如xpath、CSS选择器等&#xff09;来找到这些元素。 可以使用find_element_by_xpath或find_elemen…

按键的短按、长按和连续的划分

在实际生活中&#xff0c;我们使用到的按键在短按、长按和按键松开时都会触发不同的功能。按键短按后松开和长按后松开的应用比短按和长按的应用较少&#xff0c;我了解的按键短按后松开和长按后松开的应用是在点动控制和长动控制中。这里主要讨论按键的短按、长按和连续这三种…

基于ConvNeXt网络的图像识别

1、前言 ConvNeXt 网络基于传统的卷积神经网络&#xff0c;与当下 transformer当道而言简直是一股清流 ConvNeXt并没有特别复杂或者创新的结构 ConvNeXt 网络有五种大小&#xff0c;可以参考下面 2、项目实现 完整的项目如下&#xff1a; 这里参考了网上的ConvNeXt 模型&…

计算机服务器中了devicdata勒索病毒如何解密,devicdata勒索病毒解密恢复工具

在网络技术飞速发展的时代&#xff0c;有效地利用网络开展各项工作业务&#xff0c;能够大大提升企业的生产运行效率&#xff0c;改善企业的发展运营模式&#xff0c;但如果网络利用不好就会给企业的数据安全带来严重威胁。近日&#xff0c;云天数据恢复中心接到很多企业的求助…

机柜风扇KTS011温湿度控制器KTO011风机控制温控器机械开关温控仪

品牌&#xff1a;威驰 型号&#xff1a;KTS011常开 产地&#xff1a;中国大陆 颜色分类&#xff1a;KTS011常开,KTO011常闭 KTS011与KTO011的区别 KTS011&#xff0c;常开型&#xff0c;可搭配风扇/风机使用&#xff1a;当环境温度超过温控器设定温度&#xff0c;温控…

如何挑选家用洗地机?需要注意什么?这四款洗地机性价比超高

洗地机结合了扫、拖、吸的功能&#xff0c;一台机器&#xff0c;一个推拉的动作便可以清理干净地面上的干湿垃圾&#xff0c;大大的节省了我们做家务的清洁时间&#xff0c;提升了生活质量。但是面对市面上众多的洗地机型号&#xff0c;我们要怎么去挑选呢&#xff0c;需要主要…

Goland GC

Goland GC 引用Go 1.3 mark and sweep 标记法Go 1.5 三色标记法屏障机制插入屏障删除写屏障总结 Go 1.8 混合写屏障(hybrid write barrier)机制总结 引用 https://zhuanlan.zhihu.com/p/675127867 Garbage Collection&#xff0c;缩写为GC&#xff0c;一种内存管理回收的机制…

JDK1.8 安装并配置环境变量

一、Windows 配置 1 安装文件 jdk-8u401-windows-i586.exe 2 环境变量 JAVA_HOME C:\Program Files (x86)\Java\jdk-1.8 CLASSPATH .;%JAVA_HOME%\lib\tools.jar;%JAVA_HOME%\lib\dt.jar; Path %JAVA_HOME%\bin 说明&#xff1a;Win7/Win8 中 Path 可能需要写成 ;%JAVA_HO…

新能源汽车动力电池浸没式冷却方案介绍与未来趋势

前言 新能源汽车的兴起标志着汽车工业的一次革命&#xff0c;其中动力电池的设计与性能成为了关键。浸没式冷却方案作为一种新兴的技术&#xff0c;为动力电池系统提供了有效的散热解决方案&#xff0c;其在未来的发展趋势备受关注。 一 动力电池浸没式冷却方案介绍 首先&am…
最新文章