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); }
16
学过了数组指针和指针数组,看看下面这些都是什么?
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的整形数组。