1.指针数组
什么是指针数组呢?
我们通过以前学过的数组进行类比:
- 整形数组是存放整形的数组
- 字符数组是存放字符的数组
- 所以,指针数组是存放指针(地址)的数组
整形数组的书写形式是int arr[10]
,字符指针书写形式是char arr[10]
,所以字符指针的书写形式是int *arr[10] char* arr[10]
接下来创建一个字符指针数组
int main()
{
char a = 'a';
char b = 'b';
char c = 'c';
char d = 'd';
char* arr[4] = {&a,&b,&c,&d};
return 0;
}
创建了四个
char
类型变量,将他们取地址放到字符指针数组里,这是最基本的应用
还可以将字符串放到字符指针数组里,字符指针可以存放一个一个字符串中第一个字符的地址,所以这里是将4个字符串首字符的地址存到字符指针数组里
int main()
{
char str1[] = "hello";
char str2[] = "world";
char str3[] = "byebye";
char str4[] = "world";
char* arr[4] = {str1,str2,str3,str4};
return 0;
}
还可以用一维指针数组模拟二维数组
#include <stdio.h>
int main()
{
int arr1[5] = { 1,2,3,4,5 };
int arr2[5] = { 2,3,4,5,6 };
int arr3[5] = { 3,4,5,6,7 };
int arr4[5] = { 5,6,7,8,9 };
int arr5[5] = { 0,1,0,2,0 };
int* arr[5] = { arr1,arr2,arr3,arr4 ,arr5};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
printf("%d ", *(*(arr + i) + j));
}
printf("\n");
}
return 0;
}
前面说过,对于一个指针
p
,*(p+i)
与p[i]
等价
所以上述程序中的*(*(arr + i) + j)
也可以写成arr[i][j]
,也就是如二维数组一样的写法
这个指针数组的结构:
2.数组指针
对于数组指针,还是类比其他类型指针
- 整形指针是一个指向整形变量的指针
- 字符变量是一个指向字符变量的指针
- 所以数组变量就是一个指向数组的指针
- 整形指针的类型是
int*
,字符指针的类型是char*
,所以数组指针的类型就是int(*)[10]
char ch = 'w';
char *pc = &ch;
int num = 10;
int* pi = #
int arr[10];
int(*pa)[10] = &arr;
在这个整形数组指针,*
先与pa
结合:(*pa)
,所以int(*pa)[10]
是一个指针
在这里赋给数组指针的是数组名取地址,那么数组名和数组名取地址有什么区别呢?请点击跳转另一篇文章:数组与地址,数组名到底是什么?
数组指针到底怎么用呢?
之前如果要输出一个整形数组,我们可以使用指针,这里的指针通常是数组元素首地址
但是如果非要用数组指针输出数组中的元素也是可以的
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
int(*p)[10] = &arr;
for (int i = 0; i < 10; i++)
{
printf("%d ", (*p)[i]);
}
return 0;
}
这里的p
是一个数组指针,先将解引用*p
,得到数组,然后通过下标访问(*p)[i])
就可以得到数组元素了
但是这样做是很别扭的,不如直接用整形指针输出
其实 数组指针在一位数组中用的不多,在二维数组中会用到
在以往的对于二维数组的传参,定义函数时,在参数列表中最简单的写法是直接以二维数组的形式传形参
void print(int arr[3][4], int x, int y) //直接以二维数组的形式写是最简单的
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
printf("%d ", arr[i][j]);
}
printf("\n");
}
}
int main()
{
int arr[10] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
print(arr, 3, 4);
}
但是,对于一位数组int arr[10]
,如果在函数中想要接受它,不但可以以数组的形式接受,用一个一级指针接受也是可以的
void printf(int arr[10],int len) //可以用数组的形式接收
{
;
}
void printf(int *arr,int len) //也可以用指针的形式接收
{
;
}
int main()
{
int arr[10] = { 1,2,3,4,5,6,7,8,9,10};
print(arr,10);
}
如果也想要用一个指针变量去接收二维数组传参就略有不同了
函数实参传一个二维数组名过去,数组名是数组首元素地址,所以二维数组数组名就是一个一维数组的地址,这个二维数组名其实就是一个数组指针,所以在函数中要用一个数组指针去接收
void print(int(*arr)[4],int x,int y) //用一个数组指针去接收
{
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y;j++)
{
printf("%d ", (*(arr+i))[j]);
}
printf("\n");
}
}
int main()
{
int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
print(arr, 3, 4);
}
学过了数组指针和指针数组,看看下面这些都是什么?
int arr[5];
int *parr1[10];
int (*parr2)[10];
int (*parr3[10])[5];
int arr[5]
,是一个长度为5的整形数组int *parr1[10]
,是一个整形指针数组,长度为10,里面存放整形指针int (*parr2)[10]
,是一个数组指针,parr2
指向一个长度为10的整形指针int (*parr3[10])[5]
,这个比较复杂,一步一步分析,首先看名称parr3
先与[10]
结合,所以这是一个数组,长度为10,然后剩下int(*)[5]
,所以在数组parr3
中存放的是类型为int(*)[5]
的数组指针,它指向一个长度为5的整形数组。