关于我、重生到500年前凭借C语言改变世界科技vlog.12——深入理解指针(2)

ops/2024/10/30 16:09:00/

文章目录

  • 1.数组名与地址
    • 1.1 arr
    • 1.2 sizeof(arr)
    • 1.3 &arr
  • 2.指针访问数组
  • 3.一维数组传参本质
  • 4.指针数组
  • 5.二级指针
  • 希望读者们多多三连支持
  • 小编会继续更新
  • 你们的鼓励就是我前进的动力!

1.数组名与地址

有这么一个数组,数组名为 arr

int arr[10] = {1,2,3,4,5,6,7,8,9}
int *p = &arr[0]

在这里 &arr[0] 指的是首元素地址,其实本质上数组名就代表的是数组首元素地址
接下来我们将对以下几个名字进行区分

1.arr
2.sizeof(arr)
3.&arr

1.1 arr

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("&arr[0] = %p\n", &arr[0]);printf("arr = %p\n", arr);return 0;
}

根据以上保留取地址符&和只用数组名,打印对应的地址可以发现
在这里插入图片描述
两个的地址都相同,这就说明了 &arr[0] = arr,即数组名就是首元素地址

1.2 sizeof(arr)

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%d\n", sizeof(arr));return 0;
}

这里关键字 sizeof 计算 arr 的大小,你可能会觉得应该输出首元素的大小?
在这里插入图片描述
不,这里的 arr 不代表首元素大小,而是表示整个数组,计算整个数组的大小,单位是字节

1.3 &arr

#include <stdio.h>
int main()
{int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };printf("%p\n", &arr);printf("%p\n", &arr+1);return 0;
}

打印 &arr 和 &arr+1 地址,假设他是跳过一个字节的地址
在这里插入图片描述
很显然,根据代码结果,两段代码地址相差40,那么假设就是错的,所以 &arr 表示的是整个数组的大小

总结:只有 &arr 和 sizeof(arr) 有特殊含义,其他情况下的数组名都代表数组首元素地址

2.指针访问数组

#include <stdio.h>
int main()
{int arr[10] = {0};//输⼊int i = 0;int sz = sizeof(arr)/sizeof(arr[0]);//输⼊int* p = arr;for(i=0; i<sz; i++){scanf("%d", p+i);//scanf("%d", arr+i);//也可以这样写}//输出for(i=0; i<sz; i++){printf("%d ", p[i]);}return 0;
}

使用指针访问数组在一些环境下,会更接近本质,更加简洁易懂
将 *(p+i) 换成 p[i] 也是能够正常打印的
在这里解引用操作符和下标引用符产生的效果相同

本质上p[i] 是等价于 *(p+i),数组元素的访问在编译器处理的时候,也是转换成首元素的地址+偏移
量求出元素的地址,然后解引用来访问的

3.一维数组传参本质

在前面学习的函数篇章中,数组可以传递给自定义函数,那么数组传递的本质是什么呢?

#include <stdio.h>
void test(int arr[])
{int sz2 = sizeof(arr)/sizeof(arr[0]);printf("sz2 = %d\n", sz2);
}
int main()
{int arr[10] = {1,2,3,4,5,6,7,8,9,10};int sz1 = sizeof(arr)/sizeof(arr[0]);printf("sz1 = %d\n", sz1);test(arr);return 0;
}

通过以上代码调试后可以发现,sz1 = 10,sz2 = 1,同样的算法应该 sz1 = sz2 =10 ,但穿过去的形参根据结果 sizeof(arr) 只计算出一个元素的大小,前面我们提到 arr 表示首元素的地址,那么在数组传参的时候,传递的是数组名,也就是数组传参的时候传递的是首元素的地址

所以函数的形参应该用指针变量来接收一个地址,这也证实了数组传参的本质是传递首元素地址
形参部分既可以写成 int * arr 的指针形式,也可以写成 arr[ ] 的数组形式

4.指针数组

什么是数组指针?什么是指针数组?这里我们重点介绍一下指针数组
指针数组是一个数组,比如整型数组存放的数组,字符数组存放的是字符,那么指针数组存放的就是指针

int* arr[5] = 5个int*

每一个数组里的指针都指向一个地址

5.二级指针

正常的一个常见的指针是一级指针,那么在一个指针里面再嵌套一个指针就是二级指针
是变量就有地址,指针变量也不例外,比如把指针变量的地址需要存放在另一个指针变量里

#include <stdio.h>
int main()
{int i = 5;int * pi = &i;int ** pii = &pi;  return 0;
}

*pii 通过对 pii 中的地址进行解引用,这样找到的是 pi , *pii 其实访问的就是 pi
**pii 先通过 *pii 找到 pi ,然后对 pi 进行解引用操作: *pi ,那找到的是 i

博主最近在准备蓝桥杯的校内比赛,更新可能会有所减缓,大家多多谅解!😃

希望读者们多多三连支持

小编会继续更新

你们的鼓励就是我前进的动力!

在这里插入图片描述


http://www.ppmy.cn/ops/129626.html

相关文章

【Linux】ProxySQL读写分离

proxysql-2.7.1-1-centos7.x86_64.rpm 读写分离 读写分离的概念 读写分离是⼀种数据库优化技术&#xff0c;主要⽬的是通过将数据库的读操作和写操作分散到不同的数据库 实例上&#xff0c;来提⾼数据库的整体性能和可扩展性。其基本原理是让主数据库处理事务性增、改、删操…

C#判断带数字的字符串数组连续性的两种方式

给定一个包含数字的字符串数组&#xff0c;需要判断数组中每项包含的数字是否连续增长。   如果数组项中的非数字字符有规律&#xff0c;例如给数字增加固定的前缀、后缀等&#xff0c;则较快的判断方式是提前按规则生成包含连续数字的字符串数组&#xff0c;直接判断给定的字…

rtp协议:rtcp包格式和传输间隔

RTP Control Protocol -- RTCP-rtp控制协议 实时传输控制协议&#xff08;RTCP&#xff09;基于对会话中的所有参与者定期传输控制包&#xff0c;使用与数据包相同的分发机制。底层协议必须提供数据包和控制包的多路复用&#xff0c;例如使用UDP时使用不同的端口号。RTCP执行四…

2024三掌柜赠书活动第三十四期:破解深度学习

目录 前言 深度学习的基本概念 深度学习的关键技术 深度学习的实践应用 关于《破解深度学习》 编辑推荐 内容简介 作者简介 图书目录 《破解深度学习》全书速览 结束语 前言 深度学习作为人工智能领域的一个重要分支&#xff0c;近年来取得了令人瞩目的进展。从图像…

Java进阶篇设计模式之四 -----适配器模式和桥接模式

前言 在上一篇中我们学习了创建型模式的建造者模式和原型模式。本篇则来学习下结构型模式的适配器模式和桥接模式。 适配器模式 简介 适配器模式是作为两个不兼容的接口之间的桥梁。这种类型的设计模式属于结构型模式&#xff0c;它结合了两个独立接口的功能。 简单的来说就…

Spring 全家桶新人入门指南:服务调用最佳实践

spring 全家桶的整体介绍 Spring 全家桶提供了一整套解决方案&#xff0c;覆盖了从基础框架到企业级应用开发的各个方面。其中&#xff0c;Spring Boot 旨在简化新 Spring 应用的初始搭建以及开发过程&#xff0c;通过约定大于配置的原则来快速启动项目&#xff1b;Spring MVC…

巴西电商市场神仙打架,美客多多月蝉联访问量榜首,9月Temu位居巴西APP下载量榜首

巴西电商市场近年来呈现出强劲的增长趋势&#xff0c;预计2024年巴西电子商务市场的销售额将达到2043亿雷亚尔&#xff08;约合373亿美元&#xff09;&#xff0c;同比增长约10%。作为拉美地区最大的经济体&#xff0c;巴西吸引了众多电商平台和商家&#xff0c;巴西电商市场竞…

Hyperledger Fabric有那些核心技术,和其他区块链对比Hyperledger Fabric有那些优势

Hyperledger Fabric是一个模块化、权限化的企业级区块链平台&#xff0c;与比特币、以太坊等公有链相比&#xff0c;Fabric主要为私有链或联盟链设计&#xff0c;适用于企业应用。它包含多项核心技术&#xff0c;使其在企业级区块链应用中具有独特优势。以下是Fabric的核心技术…