当前位置: 首页 > news >正文

深入了解指针(3)

文章目录

  • 数组名的理解
  • 对arr[i]的理解
  • 一维数组传参的本质
  • 二级指针
  • 指针数组
    • 指针数组的用处
  • 总结

这里是think的博客

希望可以一起交流知识,一起think

今天我们来学习指针(3)

一起来think吧

数组名的理解

//测试环境:X86#include<stdio.h>intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};printf("&arr[0] = %p\n",&arr[0]);printf("arr = %p\n",arr);return0;}

我们发现数组名和数组首元素的地址打印出的结果⼀模一样,数组名就是数组首元素(第⼀个元素)的地址。

例外:
sizeof(数组名),sizeof中单独放数组名,这里的数组名表示整个数组,计算的是整个数组的大小,单位是字节。
&数组名,这里的数组名表示整个数组,取出的是整个数组的地址。(整个数组的地址和数组首元素的地址是有区别的)

好的,这个是常规的讲法,那么我把我学习中体会的理解说一下:

  • 实际上数组名就是整个数组,在定义的时候int arr[]={1,2,3};这个时候arr就是整个数组,这个时候arr没有退化,因为逻辑上没人使用也就不用退化。
  • 当sizeof(数组名),&数组名的时候这个时候数组名也不退化,为什么?因为逻辑上这个时候sizeof要的就是数组的大小,&也要的就是整个数组的地址,那么就不用退化。
  • 什么时候数组名的意义会从整个数组退化到数组首元素的地址呢?
  • 下标索引,正常单独使用arr等大部分情况,那么为什么要退化?为了保证逻辑通顺,在大多数情况下,arr的意义会退化为首元素的地址。
  • 举个例子,int a = arr[i];,实际上arr[i]也就是*(arr+i),arr是首元素的地址的话,是不是刚刚好就可以索引到对应位置,找到对应的值了。
  • 如果不退化的话,你很难去思考怎么利用整个数组这个概念去找到数组中对应的值的,所以数组退化为了保证表达式逻辑通顺、语言使用简洁。
  • 再举一个例子如果arr不退化为首元素地址的话,还是整个数组的话,那么arr打印出来是什么?显然逻辑上是不清楚的。

再来谈谈下一个话题,关于arr和&arr的区别,一个是首元素的地址,一个是整个数组的地址,他们两个到底有什么区别?

这就是我上篇博客深入了解指针(2)所讲到的,解引用后可以改变的内存空间有多少?指针类型的差别就在±1的步子有多大?,这些就取决于指针类型

这里我们先不谈解引用,先来看看±1的步子的差别

//测试环境:X86#include<stdio.h>intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};printf("&arr[0] = %p\n",&arr[0]);printf("&arr[0]+1 = %p\n",&arr[0]+1);printf("arr = %p\n",arr);printf("arr+1 = %p\n",arr+1);printf("&arr = %p\n",&arr);printf("&arr+1 = %p\n",&arr+1);return0;}


明显看出首元素地址+1跳过4个字节,而&arr即整个数组地址+1,跳过40个字节。

对arr[i]的理解

for(i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}

for(i = 0; i < sz; i++)
{
printf("%d ", *(arr+i));
}
return 0;

通过这两个for循环可以很明白的看出arr[i]其实就是*(arr+i)来的。所以其实i[arr]这种形式也是可以的哦,只是没有人会这么写。

一维数组传参的本质

#include<stdio.h>//测试环境是x86voidtest(intarr[]){intsz2=sizeof(arr)/sizeof(arr[0]);printf("sz2 = %d\n",sz2);}intmain(){intarr[10]={1,2,3,4,5,6,7,8,9,10};intsz1=sizeof(arr)/sizeof(arr[0]);printf("sz1 = %d\n",sz1);test(arr);return0;}

这里的这个int arr[ ]是函数形参中的,其中arr会退化为首元素的地址,所以他的实际的形式就是int* arr,
如果[ ]里面还有数字,编译器也是直接忽略的,会把它变为int*arr再往下编译。

其中因为传参数的时候,就是传的首元素的地址,所以sz2就是1了,地址是4个字节,int也是4个字节,其中sz1是10,是因为arr是数组名,定义的时候没有退化,移到sizeof中的时候也没有退化,所以是sz1是10。

而这样的话,因为传递的是指针,所以函数内部就无法用sizeof来求大小了,只能外部传递。

二级指针

#include<stdio.h>intmain(){inta=10;int*pa=&a;int**ppa=&pa;return0;}


**ppa 先通过 *ppa 找到 pa ,然后对 pa 进行解引用操作: *pa ,那找到的是a。

指针数组

指针数组是一个数组,一个词的本质是它的最后第一个名词,那么指针数组的本质就是数组,正如整型数组和字符数组都是数组来类比得到的。

指针数组的用处

#include<stdio.h>intmain(){intarr1[]={1,2,3,4,5};intarr2[]={2,3,4,5,6};intarr3[]={3,4,5,6,7};//数组名是数组⾸元素的地址,类型是int*的,就可以存放在parr数组中int*parr[3]={arr1,arr2,arr3};inti=0;intj=0;for(i=0;i<3;i++){for(j=0;j<5;j++){printf("%d ",parr[i][j]);}printf("\n");}return0;}


parr[i] 是访问 parr 数组的元素, parr[i] 找到的数组元素指向了整型类型的一维数组, parr[i][j] 就是整型类型的一维数组中的元素。
上述的代码模拟出二维数组的效果,实际上并非完全是二维数组,因为每一行并非是连续的。

总结

谢谢观看!

http://www.jsqmd.com/news/868587/

相关文章:

  • 泰国双清包税哪家好?泰国清关哪家强?2026泰国海运清关强的公司+泰国陆运清关强的公司合集 - 栗子测评
  • Golang技术周刊 2026年第16周
  • 别再死磕修改了!paperxie 一站式搞定论文查重与降 AIGC 率,毕业党速码
  • 【编号110】64个地级市土地利用图
  • 开源fNIRS脑机接口帽技术解析与应用
  • 2026避雷塔厂家推荐:新疆角钢塔厂家+变电站架构+新疆钢管塔厂家+钢管杆厂家推荐精选 - 栗子测评
  • 2026 小众暴利 AI 项目,AI短剧带货,简单复制就能盈利
  • 开发靠 AI 提效,测试成最大瓶颈,现状过于真实
  • tensorflow:昇腾CANN的TensorFlow适配层
  • Python之anonymate包语法、参数和实际应用案例
  • c#基础知识合集08 随机数 DateTime
  • 衔接器CC Switch 小白图文安装,接入Claude Opus4.7+deekseep V4 +千问等等都不在话下,再也不用担心无法配置几个第三方大模型。
  • 如何重新定义华硕笔记本性能管理:探索G-Helper的轻量化解决方案
  • Cortex-M3/M4处理器模式判断与调试技巧
  • 2026电力金具厂家推荐:铁附件加工厂家+绝缘子厂家推荐名录 - 栗子测评
  • Ollama API 详解(学习笔记)
  • 到底什么是 AI 测试?AI 测试与传统测试的区别?
  • 量子计算与人工智能融合:技术原理与应用前景
  • 魔兽争霸3终极兼容方案:5分钟解决Win10/Win11运行问题
  • Python __slots__ 入门指南
  • 北光恒电:安捷伦DSOS系列示波器(DSOS104/254/404/804)不开机、输出不正常故障排查
  • 2026新疆电力铁塔厂家全梳理:电力铁塔生产厂家+高压铁塔定制厂家+高压输变电塔厂家推荐 - 栗子测评
  • BarrageGrab:构建企业级直播弹幕实时采集系统的技术架构与实践指南
  • 从对话框到具身:AI 交互方式的深层变化
  • A51汇编器Error 21解析与8051开发实践
  • Hermes agent 部署安装windows+D盘超详细步骤
  • 第1章:AI Agent 架构与核心组件
  • CANN 加速库实战:FlashAttention 让大模型推理吞吐翻 3 倍
  • 2026年评价高的惠州短视频剪辑/惠州短视频运营专业公司推荐 - 品牌宣传支持者
  • AgentScope Harness