物联网/嵌入式工程师
面向零基础保姆式教学+简历指导+1V1模拟面试+3次内推,助力轻松就业!
在前面及小结中,我们学习了指针和数组的概念,看起来这是两个完全不同的东西。但其实他们两者是紧密相关的,本小结我们就来探讨一下指针和数组的联系。
我们在定义数组的时候,常常这样定义,int arr[5];
在 C++ 中,数组表示的是一段连续的内存存储空间
如上图,每个元素之间是没有空隙的,这样每个元素的内存地址,其实也是有规律可循的。可以写这样一个程序,来验证我们的想法:
#include <stdio.h> int main(int argc,char **argv) { int array[5]; printf("array[0]: %p\n", &array[0]); // %p 用来打印数组的地址 printf("array[1]: %p\n", &array[1]); printf("array[2]: %p\n", &array[2]); printf("array[3]: %p\n", &array[3]); printf("array[4]: %p\n", &array[4]); return 0; }
程序运行结果如下:
array[0]: 0x7ffee9d81490 array[1]: 0x7ffee9d81494 array[2]: 0x7ffee9d81498 array[3]: 0x7ffee9d8149c array[4]: 0x7ffee9d814a0
指针的地址以16进制的方式输出,可以看出,这几个地址中,每两个相邻的地址都相差 4 ,而每一个元素都是 int类型,int 占 4 个字节大小,说明他们确实是紧密相连的。
验证了数组的地址之后,再来看看数组是如何访问数组中的元素的。假设我们想要访问第 2 个元素(从 0 开始)
array[1];
那么 C++ 在碰到这行代码的时候,是先拿到第 2 个元素的地址,然后通过地址去访问元素,那么如何拿到第二个元素的地址呢?刚刚的实验证明,数组中元素的地址都是等差的,所以只要拿到第一个元素的地址,再加上相应元素的偏差,就可以拿到第二个元素的地址了。
那么,对于数组来说,第一个元素的地址是什么的?答案是数组名。
我们再尝试写一个测试程序
#include <stdio.h> int main(int argc,char **argv) { int array[5]; printf("array: %p\n", array); printf("array[0]: %p\n", &array[0]); // %p 用来打印数组的地址 printf("array[1]: %p\n", &array[1]); printf("array[2]: %p\n", &array[2]); printf("array[3]: %p\n", &array[3]); printf("array[4]: %p\n", &array[4]); return 0; }
程序运行结果如下:
array: 0x7ffeefa29490 array[0]: 0x7ffeefa29490 array[1]: 0x7ffeefa29494 array[2]: 0x7ffeefa29498 array[3]: 0x7ffeefa2949c array[4]: 0x7ffeefa294a0
我们发现,直接输出 array 和首元素的地址,是一模一样的,那么就可以得出一个结论:数组名是一个指向数组首元素的指针
但是这个指针和我们常见的指针有一些不一样的地方,这个指针是一个常量,所以我们是不可以对其进行修改的。也就是说,我们不能对其进行 array = p 或者 array++ 这样包含重新赋值的操作,但是我们仍然可以用指针的用法来操作他。
例如,使用指针的加减法来访问对应的元素
#include <stdio.h> int main(int argc,char **argv) { int array[5]; *(array + 2) = 1; return 0; }
代码中的 *(array + 2) = 1;
就等价于 array[2] = 1;
我们在前面讲过 malloc 分配内存的用法。来看一个例子
#include <stdio.h> int main(int argc,char **argv) { int * p = (int *)malloc(5 * sizeof(int)); free(p); return 0; }
在上面的程序中,我们分配出来了一个 5 个 int 大小的储存空间:
在这块储存空间内,可以存放 5 个 int 类型的数字,假如想要访问第 3 个数字,我们可以把指针向后移动两个元素的位置,写成 *(p + 2)
那么指针可不可以按照数组的访问方式去访问呢?p[2]
其实也是可以的,p[2]
和*(p + 2)
在这里是等价的。
请验证,完成请求
由于请求次数过多,请先验证,完成再次请求
打开微信扫码自动绑定
绑定后可得到
使用 Ctrl+D 可将课程添加到书签
举报