指针(2)--指针与数组

简介: 指针(2)--指针与数组

1.数组名

先看一个案例

在这个代码中,我们提取了数组的首字母的地址和数组名来进行打印,结果是这样的:

可以发现它们两个的地址是相同的,所以我们可以得出

在通常情况下,数组名表示的就是数组首元素(第⼀个元素)的地址。

再来看一个案例:

在这个代码中,我们打印sizeof(数组名),结果是这样的:

理论上来说如果数组名是数组首元素的地址,那打印出来应该是4或8也就是一个元素所占的字节,但这里却是40。

别急,再看一个案例:

这里我们打印数组名和&数组名,也就是取地址数组名,结果是这样的:

这里我们不看打印结果,直接看类型,可见一个是int[10]一个是int[10]* 也就说一个是数组一个是数组解引用

所以除了通常情况下,还有两个例外:

• sizeof(数组名),sizeof中单独放数组名,这⾥的数组名表示整个数组,计算的是整个数组的大小,单位是字节

• &数组名,这里的数组名表示整个数组,取出的是整个数组的地址(整个数组的地址和数组首元素的地址是有区别的)

我们还可以通过另一个代码来更好理解第二个例外:

我们发现:

&arr[0]和&arr[0]+1相差4个字节,arr和arr+1 相差4个字节,是因为&arr[0] 和 arr 都是首元素的地址,+1就是跳过⼀个元素。

但是&arr 和 &arr+1相差40个字节,这就是因为&arr是数组的地址,+1 操作是跳过整个数组的。

2.使用指针访问数组

既然arr是数组的首元素的地址,那么它赋值给p时,其实可以认为p等价于arr。所以arr[i]也就等价于p[i]。

我们需要知道的一个很重要的事实是:

数组其实就是指针,它的底层含义就是地址。

从1中我们也得知数组名就是其首元素地址。

所以其实满足这样的关系式:

arr[i]==*(arr+i)==*(i+arr)==i[arr](满足交换律)

数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移量求出元素的地址,然后解引用来访问的。

3.一维数组传参本质

数组传参本质上传的是数组首元素的地址。sz1是整个数组元素的个数(因为它是直接打印主函数中的数组元素个数);

而sz2是函数中的数组元素的个数,但这里其实取的只是首元素,也就只有一个了。

函数形参的部分是使用指针变量来接收首元素的地址。那么在函数内部我们写 sizeof(arr) 计算的是⼀个地址的大小(单位字节)而不是数组的大小(单位字节)。

正是因为函数的参数部分是本质是指针,所以在函数内部是没办法求数组元素个数的。

4.二级指针/多级指针

指向某一个变量的地址就是指针,当这个变量本身不是指针时,那么这里的指针叫做一级指针。

我们知道,指针变量是指向某一类型数据的内存地址的变量,它作为变量的本质是不会改变的。

那么只要是变量就会有地址。

所以指针变量的地址就叫做二级指针。它是指向指针的指针。

那么如果我们要通过pp来找到或者改变a变量,就要解引用两次。

既然二级指针是指向指针的指针,那么肯定就有指向二级指针的指针,被称为三级指针,还有四级指针五级指针...它们都被统称为多级指针。

5.指针数组

这个名词的主体是数组,所以顾名思义:

指针数组就是数组内所有元素都是指针的数组,也就是用来存放指针的数组。        

对比两个数组,它们的区别在于一个数组内的元素类型是整型int,另一个是整形指针int*。

既然指针数组的每一个元素都是地址,那么元素的数量也就是数组内指向的地址的数量。

6.指针数组与数组指针

指针数组是元素是指针的一类数组,它的本质是数组。

数组指针是指向某个数组的指针,它的本质是指针。

7.指针数组与普通数组的联系

1. 数据类型不同

普通数组的数据类型是普通的类型,但指针数组的数据类型实际上是普通的类型再加上*号,用来表明该数据是指针。

2. 存储的内容不同

普通数组直接存储数据的值,而指针数组存储的是指针,即存储了数据的内存地址。

3. 访问方式

普通数组可以直接通过下标访问数组中的元素,而指针数组需要通过指针来访问数组中的元素,即先获取指针,然后通过指针访问数据。

在这里我们可以思考:是否可以用指针数组来模拟实现二维数组呢?毕竟只需要获取指针就可以访问数据,也就可以模拟实现二维数组了。

注意:上述的代码模拟出二维数组的效果,实际上并非完全是⼆维数组,因为每⼀行并非是连续的。

4. 灵活性

指针数组的元素可以指向不同类型的数据,而普通数组的元素必须是相同类型的数据。

总而言之,指针数组它也是一个数组,只不过有它特殊的用法。

目录
相关文章
|
2月前
使用指针访问数组元素
【10月更文挑战第30天】使用指针访问数组元素。
40 3
|
2月前
|
存储 程序员 编译器
C 语言数组与指针的深度剖析与应用
在C语言中,数组与指针是核心概念,二者既独立又紧密相连。数组是在连续内存中存储相同类型数据的结构,而指针则存储内存地址,二者结合可在数据处理、函数传参等方面发挥巨大作用。掌握它们的特性和关系,对于优化程序性能、灵活处理数据结构至关重要。
|
2月前
|
存储 C语言 计算机视觉
在C语言中指针数组和数组指针在动态内存分配中的应用
在C语言中,指针数组和数组指针均可用于动态内存分配。指针数组是数组的每个元素都是指针,可用于指向多个动态分配的内存块;数组指针则指向一个数组,可动态分配和管理大型数据结构。两者结合使用,灵活高效地管理内存。
|
2月前
|
容器
在使用指针数组进行动态内存分配时,如何避免内存泄漏
在使用指针数组进行动态内存分配时,避免内存泄漏的关键在于确保每个分配的内存块都能被正确释放。具体做法包括:1. 分配后立即检查是否成功;2. 使用完成后及时释放内存;3. 避免重复释放同一内存地址;4. 尽量使用智能指针或容器类管理内存。
|
2月前
|
存储 NoSQL 编译器
C 语言中指针数组与数组指针的辨析与应用
在C语言中,指针数组和数组指针是两个容易混淆但用途不同的概念。指针数组是一个数组,其元素是指针类型;而数组指针是指向数组的指针。两者在声明、使用及内存布局上各有特点,正确理解它们有助于更高效地编程。
|
2月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
61 4
|
2月前
使用指针访问数组元素
【10月更文挑战第31天】使用指针访问数组元素。
53 2
|
2月前
|
算法 索引
单链表题+数组题(快慢指针和左右指针)
单链表题+数组题(快慢指针和左右指针)
41 1
|
3月前
|
存储
如何使用指针数组来实现动态二维数组
指针数组可以用来实现动态二维数组。首先,定义一个指向指针的指针变量,并使用 `malloc` 为它分配内存,然后为每个子数组分配内存。通过这种方式,可以灵活地创建和管理不同大小的二维数组。
|
3月前
|
存储
如何通过指针数组来实现二维数组?
介绍了二维数组和指针数组的概念及其区别,详细讲解了如何使用指针数组模拟二维数组,包括定义与分配内存、访问和赋值元素、以及正确释放内存的步骤,适用于需要动态处理二维数据的场景。