C语言指针进阶:数组与指针的联系

目录

  • 1. 数组名的本质
  • 2. 使用指针访问数组
  • 3. 一维数组传参的本质
  • 4. 二级指针
  • 5. 指针数组
    • 5.1 指针数组模拟二维数组


正文开始。

1. 数组名的本质

数组名代表着这个数组中第一个元素的地址

例如:

int arr[4] = { 1,2,3,4 };
int *p1 = &arr[0];
int *p2 = arr;

上述代码中指针变量p1p2所存储的地址是相同的。

数组名代表着数组中元素首元素的地址,但有两个特例需要特别关注:

  • sizeof(arr_name):sizeof 中单独放数组名,这里的数组名代表着整个数组,计算的是整个数组的大小,单位是字节。
  • &arr_name:这里的数组名表示的整个数组,取出的是整个数组的地址

除此之外,在其他任何地方使用数组名,它都表示首元素的地址。

需要注意的是,整个数组的地址和首元素的地址是有所不同的。整个数组的地址所指向的对象是一个自定义的数组类型;而首元素的地址所指向的对象是首元素的类型

例如:
在这里插入图片描述
可以看到,上述代码中,&arr所指向的对象类型为int [5],大小为20个字节;而arr所指向的对象类型为int,大小为4字节。

2. 使用指针访问数组

理解了数组名的本质,那我们就可以通过指针来访问数组了。

#include <stdio.h>
int main()
{int arr[5] = { 0 };int size = sizeof(arr) / sizeof(arr[0]);int* p = arr;//p == arr == &arr[0]for(int i = 0; i < size; i++){scanf("%d", p + i);//p + 1 == arr + i == &arr[0] + i == arr[i] == p[i]}for(int i = 0; i < size; i++){printf("%d ", *(p + i));}return 0;
}

运行结果:
在这里插入图片描述

3. 一维数组传参的本质

我们时常需要将数组作为参数传递给函数,下面来讨论下一维数组传参的本质。

#include <stdio.h>
void Num(int arr[10])
{int size = sizeof(arr);printf("%d", size);
}int main()
{int arr[10] = { 0 };Num(arr);return 0;
}

32位环境下运行结果:
在这里插入图片描述
64位环境下运行结果:
在这里插入图片描述

在上述代码第11行调用函数时,函数的参数为arr,这里代表着该数组首元素的地址,所以传递进函数的参数实际上是一个地址

在函数定义时,用到了void Num(int arr[10]),其中的[10]只是一个形式上的声明,可以理解为告诉开发人员这是一个存放了十个元素的数组。

既然传入的参数本质上是一个地址,那我们当然也可以在定义函数的时候,就将参数设置为指针,例如上文代码等同于:

#include <stdio.h>
void Num(int *p)
{int size = sizeof(p);printf("%d", size);
}int main()
{int arr[10] = { 0 };Num(arr);return 0;
}

4. 二级指针

我们都知道,指针变量就是用来存放所指向对象的地址,那指针变量也是变量,是变量就有地址,那指针变量的地址存放在哪里呢?答案就是二级指针

#include <stdio.h>
int main()
{int a = 5;//一级指针,存放变量 a 的地址int* p = &a;//二级指针,存放变量 p 的地址int** pp = &p;//指针的运算//一级指针解引用,*p == a == 5int b = *p;//二级指针解引用,*pp == p,**pp == a == 5int* c = *pp;int d = **pp;return 0;
}

在这里插入图片描述

这里只对二级指针做演示,按照二级指针的定义,以此类推,就可以得出多级指针的用法,这里不再赘述。

5. 指针数组

指针数组,究竟是指针呢,还是数组呢?
我们类比一下,韭菜盒子,到底是韭菜呢,还是盒子呢,很显然,它指的是韭菜馅的盒子。
那指针数组呢?是存放指针的数组

图例:
在这里插入图片描述

5.1 指针数组模拟二维数组

#include <stdio.h>
int main()
{int arr1[5] = { 1,2,3,4,5 };int arr2[5] = { 2,3,4,5,6 };int arr3[5] = { 3,4,5,6,7 };//指针数组,每个元素都是一个指向一维数组的地址int* parr[3] = { arr1,arr2,arr3 };int i = 0;int j = 0;for(i = 0; i < 3; i++){for(j = 0;j < 5; j++){printf("%d ",parr[i][j]);//可理解为(parr[i])[j]//例如parr[1][3]//parr[1][3] == (parr[1])[3] == arr2[3] == 5}printf("\n");}return 0;
}

运行结果:
在这里插入图片描述

图解:
在这里插入图片描述
上述代码实现了二维数组的效果,但其本质上并不是二维数组,因为每一行在内存中并非是连续存储的,而二维数组的元素在内存中是连续存储的。


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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

步骤大全:网站建设3个基本流程详解

一.领取一个免费域名和SSL证书&#xff0c;和CDN 1.打开网站链接&#xff1a;https://www.rainyun.com/z22_ 2.在网站主页上&#xff0c;您会看到一个"登陆/注册"的选项。 3.点击"登陆/注册"&#xff0c;然后选择"微信登录"选项。 4.使用您的…

matlab使用教程(43)—二维曲线图绘制的基本方法

这个博客创建一个简单的曲线图并修改横纵坐标。通过更改线条颜色、线型和添加标记来自定义线图的外观。 1.创建曲线图 使用 plot 函数创建二维曲线图。例如&#xff0c;绘制从 0 到 2 π 之间的正弦函数值&#xff0c;并修改横纵坐标&#xff0c;添加图形标题。 x linspace…

unity android 打包

现在使用的unity版本hub不支持导入support&#xff0c;只能自己下载对应的支持 找到对应的sdk&#xff0c;ndk

算法库应用- 表的自然链接

功 能: 设计算法,将两个单链表数组的特定位序, 相同者,链接起来 编程人: 王涛 详细博客:https://blog.csdn.net/qq_57484399/article/details/127161982 时 间: 2024.4.14 版 本: V1.0 V1.0 main.cpp /***************************************** 功 能: 设计算法,将两个…

认识异常(2)

❤️❤️前言~&#x1f973;&#x1f389;&#x1f389;&#x1f389; hellohello~&#xff0c;大家好&#x1f495;&#x1f495;&#xff0c;这里是E绵绵呀✋✋ &#xff0c;如果觉得这篇文章还不错的话还请点赞❤️❤️收藏&#x1f49e; &#x1f49e; 关注&#x1f4a5;&a…

基于SSM+Jsp+Mysql的旅游网站设计与实现

开发语言&#xff1a;Java框架&#xff1a;ssm技术&#xff1a;JSPJDK版本&#xff1a;JDK1.8服务器&#xff1a;tomcat7数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09;数据库工具&#xff1a;Navicat11开发软件&#xff1a;eclipse/myeclipse/ideaMaven包…

74HC595引脚图时序图工作原理

74HC595和74hc164一样是在单片机系统中常用的芯片之一他的作用就是把串行的信号转为并行的信号&#xff0c;常用在各种数码管以及点阵屏的驱动芯片&#xff0c; 使用74HC595可以节约单片机mcu的io口资源&#xff0c;用3个io就可以控制8个数码管的引脚&#xff0c;他还具有一定的…

【Kafka】Kafka 架构深入

Kafka 工作流程及文件存储机制 Kafka 中消息是以 topic 进行分类的&#xff0c;生产者生产消息&#xff0c;消费者消费消息&#xff0c;都是面向 topic 的。 topic 是逻辑上的概念&#xff0c;而 partition 是物理上的概念&#xff0c;每个 partition 对应于一个 log 文件&am…

服务器docker应用一览

文章目录 一、需求概况二、业务流程三、运行效果四、实现过程1. 基础前提2. 源码放送3.核心代码4. 项目打包5.部署步骤 一、需求概况 现有某云主机服务器&#xff0c;用来做项目演示用&#xff0c;上面运行了docker应用&#xff0c;现希望有一总览页面&#xff0c;用来展示部署…

Java并发--锁

锁 volatile关键字 volatile可以保证变量的可见性&#xff0c;如果我们将变量声明为volatile&#xff0c;那么每次使用它都在主存内进行读取&#xff0c;保证其他线程能准确无误的读取到本线程对变量的修改。 底层&#xff1a; volatile关键字修饰变量的时候&#xff0c;本…

【C++庖丁解牛】底层为红黑树结构的关联式容器--哈希容器(unordered_map和unordered_set)

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 1. unordered系列关联式容…

网络篇10 | 网络层 IP

网络篇10 | 网络层 IP 01 简介02 名称解释03 IP报文格式(IPv4)1&#xff09;4位版本协议(version)2&#xff09;4位首部长度(header length)3&#xff09;8位服务类型(Type Of Service, TOS)4&#xff09;16位总长度5&#xff09;16位(分片)标识6&#xff09;3位(分片)标志7&am…