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

作者: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个字节。



  • 285
    点赞
  • 988
    收藏
    觉得还不错? 一键收藏
  • 43
    评论
评论 43
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值