目录
指针数组
指针数组是指针还是数组?
我们类比一下,整型数组,是存放整型的数组,字符数组是存放字符的数组。
那指针数组是存放指针的数组。
int* arr[5]
指针数组的每个元素都是用来存放地址(指针)的。
指针数组的每个元素是地址,又可以指向一块区域。
指针数组模拟二维数组
首先正如标题所示,指针数组只是可以模拟出二维数组,而不是真正的二维数组,因为在二维数组中各元素的地址在内存中从低地址向高地址连续存放的,而指针数组中存放的指针指向的地址之间是不连续的,例如arr1是数组的首地址,arr2是数组的首地址,而数组arr1和arr2的首地址是不连续存放的,所以不满足二维数组地址连续的这一特点。
#include<stdio.h>
int main()
{
int arr1[] = { 1,2,3,4 };
int arr2[] = { 5,6,7,8 };
int arr3[] = { 9,10,11,12 };
int* ptr[] = { arr1,arr2,arr3 };
int sz = sizeof(ptr) / sizeof(ptr[0]);
int sz1 = sizeof(arr1) / sizeof(arr1[0]);
for (int i = 0; i < sz; i++)
{
for (int j = 0; j < sz1; j++)
{
printf("%2d ", *(*(ptr + i) + j));
}
printf("\n");
}
return 0;
}
运行结果:
其中 代码*(*(ptr + i) + j) 等价于 ptr[ i ][ j ]
ptr是指针数组的首地址,ptr + i 表示在ptr数组中下标为 i 的地址即&ptr[i],解引用后 *(ptr + i) 还是一个地址(这个地址是某个数组的首元素地址即arr)。
*(*(ptr+i)+j) 这个解引用后的地址加 j 表示在某一个数组中下标为 j 的地址即&arr[j],再解引用就是这个地址中所存放的数据。
例:
ptr + 1 == &ptr[1] (ptr数组中下标为1的地址)
*(ptr + 1) == *(&ptr[1])== ptr[1] == arr2(arr2的数组首元素地址) ,*(ptr+1)+1 ==arr2+1== &arr2[1](arr2数组中下标为1的地址),*(*(ptr+1)+1 )== *( &arr2[1] ) == arr2[1] == 6,
即ptr[1][1]==6
ptr[ i ] 是访问ptr数组的元素,ptr[ i ] 找到的数组元素指向了整型的一维数组,ptr[ i ][ j ]就是整型的一位数组中的元素。
指针数组传参
定义一个指针数组:
char* arr[5] = {"hello", "world"};
若有一个函数test();
定义函数:
void test(char* arr[]);
或者:
void test(char** arr);
指针的数组传递给子函数变为指针的指针,也就是二级指针。
数组指针
数组指针是指针变量?还是数组?
数组指针是指向数组的指针,本质是指针变量。
int (*p)[10];
解释:p先和*结合,说明p是一个指针变量,然后指向的是一个大小为10个整型的数组。所以p是一个指针,指向一个数组,叫数组指针。
注意:[ ] 优先级要高于 * 号的,所以必须加上 () 来保证p先和 * 结合。去掉括号就变为指针数组了。
数组指针变量的初始化
数组指针变量是用来存放数组地址的,获得数组的地址:&数组名
如果要存放数组的地址,就得存放在数组指针变量中,如下
int (*p)[10] = &arr;
二维数组传参的本质
一个二维数组需要传给一个函数的时候,我们一般是这样写的:
#include<stdio.h>
void print(int arr[][4], int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
print(arr, 3, 4);
return 0;
}
这个代码的实参是二维数组,形参也是二维数组的形式
二维数组可以看做是每个元素是一维数组的数组,也就是二维数组的每个元素是一个一维数组。
那么二维数组的首元素就是第一行,是个一维数组。
如下图:
所以,根据数组名是数组首元素的地址这个规则,二维数组的数组名表示的就是第一行的地址,是一维数组的地址。
根据上面的例子,第一行的一维数组的类型是int [5],所以第一行的地址的类型就是数组指针类型 int (*)[5]。
那就意味着二维数组传参本质上也是传递了地址,传递的是第一行这个一维数组的地址,那么形参也可以写成指针的形式。
#include<stdio.h>
void print(int(*p)[4], int m, int n)
{
for (int i = 0; i < m; i++)
{
for (int j = 0; j < n; j++)
{
printf("%d ", *(*(p + i)+j));
}
printf("\n");
}
}
int main()
{
int arr[][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
print(arr, 3, 4);
return 0;
}
总结:二维数组传参,形参的部分可以写成数组,也可以写成指针形式。
创作不易,点个赞,谢谢💕(❁´◡`❁)