|
1. 数组指针/指针数组
数组指针是:
指向数组的指针,它本质上还是一个指针,类比普通指针
指针数组是:
一个存放指针的数组,本质上是数组,就如经常说的字符数组,整型数组一样
1.1 数组的理解
数组本质上只是编译器在内存空间上开辟的一连串的内存
而代表数组的变量其实只是这一连串内存空间的第一个元素的内存地址。
所以当你给编译器看一个数组时,他并不是像人一样能看到这个数组的全貌,他只能看到这个数组的第一个元素,并且知道这个元素的内存地址
看看这串代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a[] = {1, 2, 3, 4}; // 一个数组
printf(&#34;a的内存地址%p\na[0]的内存地址%p&#34;, &a, &a[0]);
return 0;
}
他的运行结果为:
a的内存地址0061FEC0
a[0]的内存地址0061FEC0相信你对数组有了更深的了解。
1.2 数组强制类型和下标
那么为什么定义数组需要强制类型呢?
拿int类型来说,int类型占用4个字节
在人们眼中的元素位置的+1
相当于编译器眼里的+4(4是类型占用的字节数)
所以才能精准的拿到某个元素
数组下标是怎么定义的呢?为什么下标从0开始
数组的下标也是这么来的,通过对内存地址的相加减来获取
因为编译器只记得数组第一个元素的内存地址
而下标就是让第一个元素的内存+i(i是下标)
通过下标获取元素的过程可以类比为:
- arr[1] => *(&arr +1)
先让内存地址加下标,再通过指针获取到元素
1.3 数组指针
数组指针就是指向数组第一个元素的指针,相信认真看了1.1和1.2的你能够很快理解
定义一个数组指针
int a[] = {1, 3, 5, 7}; // 一个数组
int (*p)[4] = &a; // 定义一个指针,指向数组的头元素
通过指针访问第二个数组元素:
printf(&#34;访问数组的第二个元素:%d&#34;, *(*p+1));完整代码:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int a[] = {1, 3, 5, 7}; // 一个数组
int (*p)[4] = &a; // 定义一个指针,指向数组的头元素
printf(&#34;a的内存地址%p\na[0]的内存地址%p\n&#34;, &a, &a[0]);
printf(&#34;访问数组的第二个元素:%d&#34;, *(*p+1));
return 0;
}运行结果:
a的内存地址0061FEBC
a[0]的内存地址0061FEBC
访问数组的第二个元素:31.4 指针数组
指针数组,顾名思义,他是个数组,就如经常说的字符数组,整型数组一样,只不过指针数组的定义方法和存储对象也有亿点点不一样。
定义一个指针数组(以整型为例)
int *pArr[10]; // 定义一个指针数组要注意与数组指针的定义区别开
数组指针的定义:
int (*arrP)[10];一定要注意这个括号,这涉及到了*符号的运算优先级,一但写错,就是不同的两个东西了。
简单使用:
#include <stdio.h>
int main(int argc, char const *argv[])
{
int *arr[10]; // 定义一个指针数组
int arrSize = 10; // 指针数组的长度
for (int i = 0; i < arrSize; i++)
{
arr = &i; // 将临时地址放在指针数组里
printf(&#34;数组的元素:%p\n数组元素所指向的元素%d\n&#34;, *arr);
/* code */
}
/* code */
return 0;
}输出结果:
数组的元素:0061FEA0
数组元素所指向的元素0
数组的元素:0061FEA0
数组元素所指向的元素1
数组的元素:0061FEA0
数组元素所指向的元素2
数组的元素:0061FEA0
数组元素所指向的元素3
数组的元素:0061FEA0
数组元素所指向的元素4
数组的元素:0061FEA0
数组元素所指向的元素5
数组的元素:0061FEA0
数组元素所指向的元素6
数组的元素:0061FEA0
数组元素所指向的元素7
数组的元素:0061FEA0
数组元素所指向的元素8
数组的元素:0061FEA0
数组元素所指向的元素9因为i是临时变量,所以在每次循环之后都会销毁,下次使用再次开辟,所以内存地址是一样的。
为了帮助大家,轻松,高效学习C语言/C++,给大家分享我收集的资源,从最零基础开始的,帮助大家在学习C语言的道路上披荆斩棘!点击上方即可获取,还可以一起来学习交流嗷 |
|