在深入理解指针end中,我在最后写了一长段代码
#include<stdio.h>
void test1(int arr[][5], int x, int y)
//void test1(int(*p)[5], int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
//printf("%d ", *(*(p + i) + j));
printf("%d ", arr[i][j]);
}
printf("\n");
}
printf("\n");
}
void test2(int* p[5], int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
printf("%d ", p[i][j]);
//printf("%d ", *(*(p + i) + j));
}
printf("\n");
}
}
int main()
{
int arr1[5] = { 1,2,3,0,0 };
int arr2[5] = { 4,5,6,0,0 };
int arr3[5] = { 7,8,9,0,0 };
int arr4[3][5] = { {1,2,3,0,0},{4,5,6,0,0},{7,8,9,0,0} };
int* (p[3])[5] = { arr1,arr2,arr3 };
test1(arr4, 3, 5);
test2(p, 3, 5);
return 0;
}
现在我们来拆解一下这段代码。
1:理解二维数组的本质
二维数组就是多个一维数组的集合,元素就是一维数组。
二维数组数组名是第一行一维数组的地址,是第一行数组的地址,也是是第一行一维数组里面第一个元素的地址!!!!
如图
2:理解数组指针数组的本质
数组指针数组是一个数组,数组里面的元素是数组指针。
数组指针,就是存放数组的指针。
我们来层层破茧,来慢点理解其本质
先理解一维数组和指针的关系,也就是数组指针和数组的关系
如图
数组指针的打印的地址和一维数组的地址一样。
我们数组指针数组,就是把上面的三个数组指针放到数组里面。
如图可看,p1,2,3在数组指针数组打印的地址不是一维数组的地址了。
p1,2,3也是变量,是变量就要开辟新的内存。所以我们打印的是p,1,2,3所占的地址
如图可看
数组arr4也是新开辟的也由属于他自己的内存,但是我图上没画。
记住,是变量就要开辟空间,指针变量也是变量
但是我们可以借助*接引用来直接实现arr4中打印一维数组的地址
电脑中每一次打印地址是会变的
于此我就讲解完了,数组指针数组,数组指针的本质。
3:二维数组和数组指针数组的关系
二维数组,可以看出多个一维数组的集合
数组指针数组,可以看成多个数组指针的集合
而一维数组首元素的地址一般都代表整个指针的地址。我们在进行数组指针变量初始化是,也可以看成是把首元素的地址放在了数组指针变量中。
4:分析代码
由此我们开始理解最开始的代码
int main()
{
int arr1[5] = { 1,2,3,0,0 };
int arr2[5] = { 4,5,6,0,0 };
int arr3[5] = { 7,8,9,0,0 };
int arr4[3][5] = { {1,2,3,0,0},{4,5,6,0,0},{7,8,9,0,0} };
int* (p[3])[5] = { arr1,arr2,arr3 };
test1(arr4, 3, 5);
test2(p, 3, 5);
return 0;
}
我定义了,一个二维数组arr4和一个数组指针数组p[3]
这个数组指针数组的类型是int*()[5]。
我们向函数传递的是数组,传递的是数组,传递的是数组!!!!
现在我们来分析test1和test2函数
1:test1
void test1(int arr[][5], int x, int y)
//void test1(int(*p)[5], int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
//printf("%d ", *(*(p + i) + j));
printf("%d ", arr[i][j]);
}
printf("\n");
}
printf("\n");
}
我们传递的是arr4数组,数组是,一个五列元素的一维数组集合起来的。是非常正常的打印二维数组的方式。
我们看//部分的代码
void test1(int(*p)[5], int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
printf("%d ", *(*(p + i) + j));
}
printf("\n");
}
printf("\n");
}
这个是直接使用指针来接收二维数组,p是一个指针,指针类型是int () [5];
通过解引用p我们可以逐次访问二维数组
*(p+i)表示访问第一行的元素,也是访问第一行的首元素地址
*(*(p+i)+j)表示访问第i行的第j个元素,因为+j就是将指向首元素的地址往后移动j个单位
2:test2
void test2(int* p[5], int x, int y)
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
printf("%d ", p[i][j]);
//printf("%d ", *(*(p + i) + j));
}
printf("\n");
}
}
这个就是直接接收的数组指针数组,p表示的是数组,数组元素的类型是int* [5]的
打印我们可以直接使用二维数组的打印方式,都是数组了,推理一下也就可以直接使用数组常规的打印方式。
看//部分
//部分是用指针来打印的,逻辑和test1差不多。
*(p+i),是把p这个数组名当成了数组首元素的地址。
单独的一个数组名是可以当首元素的地址,这个结论是前面说过的。
标签:test1,int,地址,二维,数组,printf,指针 From: https://blog.csdn.net/2403_87752060/article/details/143634130