首页 > 其他分享 >深入理解指针3:

深入理解指针3:

时间:2024-11-23 15:00:29浏览次数:11  
标签:arr 元素 地址 数组名 理解 深入 数组 指针

目录:

(1):数组名的理解 

(2):使用指针访问数组

(3):一维数组传参的本质

(4):冒泡排序

(5):二级指针

(6):指针数组

(7):指针数组模拟二维数组

(1):数组名的理解:

1——1引入:

在深入理解指针1,2中使用指针访问数组时,有这样的代码:

我们这里使用&arr[0]的方式拿到了第一个元素的地址,但是数组名本质就是数组到首元素的地址。

从这一组的代码测试来看:打印数组名和数组首元素的地址是一样的

得到结论:数组名就是数组首元素的地址。

1——2:数组名代表是整个数组的两个特例:

了解了这一点时让我们来看这个案例:

输出结果是:40。如果arr是数组首元素的地址的话,应该输出是4 \ 8才对,为什么是40呢?

注:数组名是数组首元素的地址不假,但是有两个例外。

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

2:&数组名:这里的数组名也表示整个数组。取出的是证书组队地址

(除此之外,任何地方使用的数组名,都表示数组首元素的地址)

1——3:地址的加1比较:

接下来我们再来看这个代码

三个打印的结果又一样了

当给他们后面都加1时:这时可以看出不同了。

(1)&arr[0] +1 和 arr + 1地址都跳过了4个字节的大小====>因为他们都是首元素的大小,

+1就是跳过一个元素

(2)1:而&arr +1,加了28,28是16进制的数据,转化为10进制是40个字节====>因为&arr是数组的地址,+ 1 的操作就是跳过了一个数组的大小。

地址+1:跳过多少个字节和什么有关系呢?——指针类型

(2)使用指针访问数组:

访问数组内容:

方法1:最原始的方法,

方法2:用指针访问数组内容:

循环中 pa+i代表的是下标为i这个元素的地址

(变式1)

让p++的方式,也可以把数组打印出来。

(变式2)

自己输入也是可以的

(变式3)在输入时直接让p自己++

在打印时要让p重新指向arr的第一个元素,因为在输入结束后p指向了数组末尾的元素,若不使p回归,则会指向数组的第11个元素====>随机值.

(变式4)

arr是数组的首个元素的地址, int*p=arr存入了arr的地址

arr的类型是int*,p的类型也是int*=====>p等价于arr,这种写法也可行的

(变式5)

这种方式可以打印出来===>这种操作为什么可行呢?

实际上,编译器在属组访问元素的时候

arr[ i ]会被转移成   *(arr+i)这种方式,数组在真正访问内存时要转化为指针的形式

(3)一维数组传参的本质

了解了之前的知识,我们知道数组是可以传递给函数的,我们之前都是在函数的外部计算数组的元素个数,那么在将数组传给函数之后,在函数的内部计算数组的长度可行吗?

可以看到图中的代码,我们在main函数中计算的sz1:计算出来数组长度是10

而在函数text中计算的长度是sz2,原因是什么呢?

数组再传参的过程中,传递的是数组首元素的地址,而图中sz2的sizeof计算的是首元素的大小除下表为1的元素的大小  4 / 4=1.从而得出了1的结果===>函数内部是无法求数组的元素个数的

因为数组传参传递的是首元素的地址,同样可以用指针来接收传来的参数,

本质是指针,但是初学时写成数组的形式会更容易理解。

总结:⼀维数组传参,形参的部分可以写成数组的形式,也可以写成指针的形式。

(4)冒泡排序:

冒泡排序的核⼼思想就是:两两相邻的元素进⾏⽐较。

主函数如下所示:

Printf与bubble_sort分别是创建的两个函数:一个负责打印结果,一个负责排序

我们先来看排序函数bulle_sort

在图中我们首先创建了一个循环处理趟数:若有n个数字,趟数就是n-1,变量i代表是第几趟;

随后进入第1个循环,在每个循环中,我们要在这一趟中给数组排序

第二个循环就是负责数组进行排序:j就代表下标为j的元素;

第二个循环中sz-1-i的含义:每次比较后就会少一个元素:也就是说排序一次后就有一个元素到了该到的位置,不需要在进行排序了。

例如第一趟中i=0;sz-1-i=9,还剩余9趟,在第一趟的第二个循环中要走9趟,第一趟结束,进入第二趟:i=1;已经有一个数到达了该到的位置,sz-1-i=8,只需要在进行8趟排序即可。

现在这个排序函数我们已经了解了

但这个版本若数组本身就是正序排列,依旧要循环n-1趟——耗时大

(优化版):该版本设置了一个标志:若次趟数列已经是有序数列:直接跳出

主函数和打印函数没有改变,和上一个版本一样

在这个版本中设置了一个标志:flag,

首先假设此数组已经是有序数组,flag=1。

在进入第二层循环后,看到红色方框中if的判断条件若满足此条件时进入,进入就说明该次循环中数组无序====>将flag置为0(代表数组无序)若未进入第二趟数组,flag还是1

if(flag==1)   break;若flag=1,则证明这一趟没有交换已经有序了。跳出第二个循环

(5)二级指针:

指针变量也是变量,是变量就有地址,那么指针变变量应该存放在哪里呢

图中int**paa:int*代表ppa指向的pa是int*类型的,而后面的*代表:ppa是指针变量。

二级指针变量是用来存放一级指针变量的地址的。

对二级指针解引用是先通过二级指针找到一级指针,再对一级指针进行解引用操作,找到的是一级指针指向的变量。

(6):指针数组

指针数组是指针还是数组呢?对于这个问题,可以用类比的方法:

整形数组:存放整形的数组;

字符数组:存放字符的数组===>重点是数组

指针数组就是存放指针的数组。(指针数组的每个元素都是用来存放地址(指针)的)

指针数组的每个元素都是地址,又可以指向一块区域。

(7)指针数组模拟二维数组

标签:arr,元素,地址,数组名,理解,深入,数组,指针
From: https://blog.csdn.net/2402_88547413/article/details/143940093

相关文章

  • 深入理解指针2:
    目录:1:const修饰指针2:野指针3:assert断言4:指针的使用和传址调用(1)const修饰指针1——1const修饰变量:我们知道变量是可以修改的我们可以看到图中a直接被修改为了20。但是如果我们希望在这个变量上加一些限制,使得它不能被修改,需要怎么做呢?引出:(const的使用) 当在a前面......
  • 深入学习scanf()的使用方法
    众所周知,C语言的scanf()位于<stdio.h>,用于输入数据,但一直以来我都对它的使用方式似懂非懂,今天我们来详细聊聊它。scanf意为“scanformat”,即格式化输入,原型如下:intscanf(constchar*format,...);一、基础使用方式#include<stdio.h>intmain(){intnum=0;sca......
  • 基于Spring Boot + Vue 的应届生毕业管理系统:打造智慧化毕业管理解决方案
    个人名片......
  • x-cmd pkg | nexttrace - 可视化路由跟踪工具,支持多种 IP 数据库,助你深入解析网络路径
    目录简介快速上手安装使用功能特点竞品和相关作品进一步阅读简介nexttrace是github.com/nxtrace用Go开发的可视化路由跟踪工具,用于分析从源到目标的网络路径。它默认使用ICMP协议发起TraceRoute请求,支持IPv4和IPv6,支持指定网卡进行路由跟踪,支持TTL控......
  • 理解UART 子系统:Linux Kernel 4.9.88 中的核心结构体与设计详解
    往期内容本专栏往期内容:Uart子系统UART串口硬件介绍深入理解TTY体系:设备节点与驱动程序框架详解Linux串口应用编程:从UART到GPS模块及字符设备驱动interrupt子系统专栏:专栏地址:interrupt子系统Linux链式与层级中断控制器讲解:原理与驱动开发–末片,有专栏内容观看顺序......
  • C语言:函数指针精讲
    1、函数指针一个函数总是占用一段连续的内存区域,函数名在表达式中有事也会被转换为该函数所在内存区域的首地址,这和数组名非常类似,我们可以把函数这个首地址(或称入口地址)赋予一个指针变量,使指针变量指向函数所在的内存区域,然后通过指针变量就可以找到并调用该函数。这种指针就......
  • 你对响应式设计的理解是什么?知道它基本的原理是吗?要想兼容低版本的IE怎么做呢?
    我对响应式设计的理解是,它是一种网页设计方法,旨在使网站能够在各种设备(从桌面电脑到移动电话和平板电脑)上提供最佳的浏览体验。这意味着网站的布局、图像和内容会根据用户所使用的设备的屏幕大小和方向自动调整。响应式设计的基本原理包括:流式布局(FluidGrids):使用相对单位(如百......
  • 说说你对RESTful的理解
    RESTful,RepresentationalStateTransfer的缩写,是一种软件架构风格,它定义了一组用于创建Web服务的约束和原则。在前端开发中,我们主要通过HTTP协议与遵循RESTful原则的后端API进行交互。我的理解如下:核心概念:资源(Resources):RESTfulAPI的核心是资源。资源可以是......
  • Servlet -个人理解笔记
    Servlet的作用        Servlet主要是为了衔接web应用的前端和后端的,作为它们俩中间数据交换的桥梁,现在很多web项目都是前后端分离的,前端写前端的后端写后端的,但是他俩所用的编程语言是有区别的,怎么实现它们之间的数据交换呢?Servlet就是为了解决这个,它是用java编写的,目......
  • 深入浅出:SpringBoot启动流程源码分析(持续更新中......)最新日期:2024年10月29日
    Hello,大家好,我是此林。今天来深入底层讲一讲SpringBoot是如何启动的,也就是我们单击运行SpringBoot启动类,它底层发生了什么?SpringBoot启动类很简单,只有一行代码。我们点进run()方法。我们发现,它底层其实进行了两步操作。第一步是new出一个SpringApplication对象,第二个是......