【数组指针】 仅此一篇 让你深刻理解数组指针

2023-11-13

作者:Mitu_-_

本帖内容著作权归作者所有,转载请务必保留本文链接

数组指针

数组指针,顾名思义,就是指向数组的指针。
我们是这样定义它的:int(* p)[n] = { }; (n为要定义的个数)
按照优先级运算运算符优先级
()与[ ] 优先级相同,根据结合律,就从左向右运算。
()里是*p,先定义了指针,所以p是个指针,然后后面是[ ],才是数组,即数组指针它指向了含有n个int类型的数组。
数组指针
如上图所示,假设定义 int (*p2)[5] = { 0, 0, 0, 0, 0}; 那么p2就指向了这个包含5个int类型的数组了。
!!!注意:指向数组和指向数组首元素的地址是两码事。p2在内存中指向的是这个数组的首地址,是和数组有关联的,而绝不仅仅是指向数组首元素的地址。)

就比如:
int *p1 = b;
int a[5] = {1, 2, 3, 4, 5};
int *p2 = a;
指针p1和p2就单纯的指向了变量,p1指向了变量b的地址,p2指向的是a数组首元素的地址,而不是指向这个数组,它与整个的数组是无关的。



说了这么多,就用代码来演示吧!

正面例证:

#include <stdio.h>
int main()
{
	int temp[5] = {1, 2, 3, 4, 5};
	int (*p)[5] = &temp;
	int i;
	
	for(i = 0; i < 5; i++)
	{
		printf("%d\n", *(*p + i));
		//或者 printf("%d\n", (*p)[i]);
	 } 
	 return 0;
}

1)第一行定义了含有5个int类型的数组temp;
2)第二行就定义了一个指向含有5个int类型数组的指针p,并把temp数组的首地址给了指针p。
注意:这里为什么不直接用 int (*p)[5] = temp;呢?
这是因为虽然temp和&temp的值都是相同的,但它们的意义却是不相同的:
*** temp指的是这个数组的 第一个元素 的首地址。
*** &temp 指的是这 整个数组 的首地址。

这里如果直接用temp的话可能编译不通过,也可能编译通过,但会给出警告。这是我用dev c++编译时的警告:

[Warning] initialization from incompatible pointer type

可能你还会有点懵,接着往下看就会明白了:

3)for循环是想把数组temp里面的数字都打出来。里面为什么用*(*p + i)呢?
p所指的是数组temp的地址,
*p+i 所指的是它在数组中的位置,
*(*p + i)就表示相应位置上的值了。

结果:

在这里插入图片描述

这里用VC反汇编一下你会理解的更加透彻:
在这里插入图片描述
1)由4: 5:8:可以看到它在[ ebp - 1 ] 到 [ ebp - 14]定义了1 —— 5 这5个数字,每个数字占四个字节。总共20个字节,也就是14h。
在[ebp - 15] —— [ebp - 18]定义了数组指针。
又在[ebp - 19] —— [ebp - 1C]定义了i。

2)for里的i初始化完成后,就进入到printf里去了:请看10:
第一行:把 i 的值放入edx里。
第二行:把指针p的值也就是数组temp的首地址放入eax中。
第三行:注意:[eax+edx*4],也就是把数组temp的地址 + i * 4 送入ecx里,这就是前面所说的“ *p+i 所指的是它在数组中的位置 ”的意思了。


反面例证:

#include <stdio.h>
int main()
{
	int temp[5] = {1, 2, 3, 4, 5};
	int (*p)[5] = &temp;
	int i;
	
	for(i = 0; i < 5; i++)
	{
		printf("%d\n", *(p + i));
	 } 
	 return 0;
}

有些不太理解的小伙伴可能会这样写:printf("%d\n", *(p + i));
“p+i 就是它在数组中的位置,外面再加个取值运算符 * 就行了嘛”,其实不然,这是它的结果:
在这里插入图片描述
为什么会是这样呢???
如果上面的都看懂了,这也就不难理解了。别忘了前面所说的指向数组和指向数组首元素的地址是两码事。
这里的指针p指向的是数组temp,那么p + 1就是p + 整个temp数组的长度咯。请看上面结果的前三行
6487536 (十进制) ——→ 62FDF0(十六进制)
6487556 (十进制) ——→ 62FE04(十六进制)
6487576 (十进制) ——→ 62FE18(十六进制)

可以看出每个数据之间都差 14H,也就是数组的长度4*5=20(D)=14(H)

这是它的反汇编:
在这里插入图片描述
上面和前面的基本差不多,直接看10:
第一行:i 的值放入edx里。
第二行:注意:imul edx, edx, 14h ,imul指令是将后面两个数相乘放入第一个寄存器中,也就是把edx*14的值放入edx中。
所以反面例证里循环一次变化的地址距长度是14h,也就是20个字节; 而上面正面例证的的循环一次变化的地址长度是4h,就是4个字节。



本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【数组指针】 仅此一篇 让你深刻理解数组指针 的相关文章

随机推荐

  • 《实现VM机与本机互ping》

    实现VM机与本机互ping 1 安装VM机及对应的OS gt 到本机检测VMware Network Adapter VMnet8是否已经生成 网上邻居 网络连接 2 查看 VMware Network Adapter VMnet8 网络I
  • C++ for循环跳过某一项求和

    include
  • 双三次插值及Matlab实现

    双三次插值及Matlab实现 一 简单实例 采用简单实例进行对双三次插值的介绍 由于双三次插值对于目标图像的某一像素进行估计时 所采用的像素信息为其周围16个像素点信息 因此不同于最近邻插值和双线性插值 此时假设有 5 5 5 times5
  • feign.FeignException: status 400 reading xxx#xxxx(String); content:

    网上有很多不一样的说话 我这个主要是因为feign的那个方法使用的 RequestParam注解 这个接收的参数长度过长造成的 这也是feign就算使用post方法 RequestParam的那个参数他会放在请求地址后面 而不是放在请求体
  • JupyterNotebook设置Python环境的方法步骤

    不多说 看链接 https stackoverflow com questions 39604271 conda environments not showing up in jupyter notebook conda activate
  • LAMP架构(qq农场)、部署jira、Java+数据库环境、

    LAMP架构 论坛 yum y install httpd yum y install mariadb mariadb server yum y install php php fpm php mysql php gd gd systemc
  • Linux多线程

    什么是线程 线程是OS调度的基本单位 其实在Linux环境下 线程可以看做是轻量级线程 Linux的线程本质仍然是进程 Linux先有进程后有线程 当创建了一个进程时 系统给他分配一段4G的虚拟内存 并在其内生成进程的PCB 当他调用相关函
  • 2023年网络安全趋势【网安人必看】

    数据安全越来越重要 我国 数据安全法 提出 建立健全数据安全治理体系 各地区部门均在探索和简历数据分类分级 重要数据识别与重点保护制度 数据安全治理不仅是一系列技术应用或产品 更是包括组织构建 规范制定 技术支撑等要素共同完成数据安全建设的
  • android Native和 Flutter 通信

    android 工程集成Flutter 集成方式主要是两种 1 工程的方式集成 首先创建android 和flutter工程 工程路径必须在同一路径下 1 在android 工程的settings gradle 文件中添加 rootProj
  • oracle的jdbc的版本与jdk对应关系

    连接类型 1 JDBC OCI oci是oracle call interface的缩写 此驱动类似于传统的ODBC 驱动 因为它需要Oracle Call Interface and Net8 所以它需要在运行使用此驱动的JAVA程序的机
  • 《软件测试》第六章 检查代码

    软件测试 第六章 检查代码 6 0 前言 6 1 静态白盒测试 检查设计和代码 6 2 正式审查 6 2 1 同事审查 6 2 2 走查 6 2 3 检验 6 3 编码标准和规范 6 4 通用代码审查清单 6 4 1 数据引用错误 6 4
  • MATLAB:画图

    目录 一 一个图上显示多个函数 二 在一个窗口显示多个图片 三 图形标注 四 线条属性 一 一个图上显示多个函数 1 相当于将上一个plot 保持住 plot B big angle x r hold on plot big angle x
  • Pandas中 DataFrame中添加一行/一列

    概述 添加行df loc 以及df append 两种方法 添加列df 和df insert 两种方法 添加行例concat 和reindex 两种方法 一 添加行 1 采用loc 方法 loc方法和iloc方法一样 可以索引DataFra
  • 定义和初始化vector对象

    和任何一种类类型一样 vector模板控制着定义和初始化向量的方法 下面列出了定义vector对象的常用方法 默认初始化 vector对象从而创建一个指定类型的空vector vector
  • Android Studio SDK Manager license 失效问题

    Before building your project you need to accept the license agreements and complete the installation of the missing comp
  • 创客教育中常见的视觉识别摄像头介绍

    近年来 创客教育 人工智能教育在中小学日渐普及 从目前中小学教育的应用层面来说 主要包含了视觉和听觉等几个领域的人工智能教学 因此 摄像头模块或传感器 作为视觉领域必不可少的教具 也被应用的越来越多 市面上越来越多的厂家或机构 也开发了许多
  • java项目时间不够怎么办_时间总是不够用怎么办?

    我在最近两年逐渐体会到两件事 1 这个世界上最公平的事情 就是每人每天拥有24个小时 2 绝大数人都是普通人 一次只能做一件事 我打游戏有三个原则 第一不玩匹配 其二不开声音 最后基本不双排 简单的三条原则 可以大大缩减我每赛季登录王者的时
  • 【git】git命令和相关脚本

    目录 git clone git checkout git diff git diff 忽略文件权限被修改的文件 对比两个分支差异 git add git pull rebase git pull git fetch git reset g
  • 如何查看linux版本 如何查看LINUX是多少位

    一 如何得知自己正在使用的linux是什么版本呢 下面的几种方法将给你带来答案 1 查看内核版本命令 1 root q1test01 cat proc version Linux version 2 6 9 22 ELsmp bhcompi
  • 【数组指针】 仅此一篇 让你深刻理解数组指针

    作者 Mitu 本帖内容著作权归作者所有 转载请务必保留本文链接 数组指针 数组指针 顾名思义 就是指向数组的指针 我们是这样定义它的 int p n n为要定义的个数 按照优先级运算 与 优先级相同 根据结合律 就从左向右运算 里是 p