首页 > 编程知识 正文

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

时间:2023-05-03 10:56:14 阅读:254750 作者:3687

作者: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("%dn", *(*p + i));//或者 printf("%dn", (*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("%dn", *(p + i)); } return 0;}

有些不太理解的小伙伴可能会这样写:printf("%dn", *(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个字节。

云分发发展迅速的原因有哪些?UsinguseState()withanobjectasstate

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。