4. 数组指针
int main() { //整型指针-指向整型的指针-存放整型变量的地址 int a = 10; int* pa = &a; //整型指针-指向字符的指针-存放字符变量的地址 char ch = 'w'; char* pc = &ch; //数组指针-指向数组的地址,存放数组变量的地址 int arr[5] = { 1,2,3,4,5 }; int(*p)[5]=&arr;//注意这个5不能省略,因为这个5是指针指向的那个数组的类型 }
一个指针只能存放一个地址,只不过这个地址是整个数组的地址
4-1 区分取地址数组名和数组名(老生常谈了)
4-1-1 sizeof(数组名):求的是该类型所定义的变量在内存中所占空间的大小,单位是字节。
int main() { int arr1[5] = { 1,2,3,4,5 }; printf("%d\n", sizeof(arr1));//32位平台下:20字节 64位平台下:20字节//类型;int[5]数组 printf("%d\n", sizeof(arr1+0));//32位平台下:4字节 64位平台下:8字节//已经不是单独的sizeof(数组名)//类型:int*指针 printf("%d\n", sizeof(arr1[0]));//32位平台下:4字节 64位平台下:8字节//类型:int*指针 return 0; }
4-1-2 &数组名,在没有+-整数时虽然地址是相同的,但是意义不同。
4-2 辨析数组指针和指针数组
图图我就省略喽!😁😁😁
int main() { //我们知道:去掉变量名剩下的部分就是变量所属的类型 //(这里可以通过调试得以验证以下猜想) //整型数组,数组类型为int [5],从左往右念就是整型数组 //特别注意:数组索引中的元素个数5也是类型的一部分 //所以int [4]和int [5]所属的是不同的类型 int arr[5] = { 1,2,3,4,5 }; //p1先和方块5(也就是[5])结合,所以整体来看p1是一个数组 //既然是数组我们关心的就是数组呢存放的是什么? //数组内有五个元素,每个元素的类型是int* 类型 //所以变量p1的类型为int* [5],从左往右念就是指针数组 int* p1[5] = { arr,&arr[1] ,&arr[2], &arr[3], &arr[4] }; //p2先和*结合,所以整体来看p2是一个指针 //既然是指针,我们关心的就是指针指向的是什么? //指针指向的是一个数组,数组内有五个元素,每个元素时int类型 //所以变量p2的类型为int[5]*,从左往右念就是数组指针 int(*p2)[5] = &arr; return 0; }
4-3 学会了?来看一个小测试题
4-4 来看一个脱裤子放屁的代码【看一看数组指针的使用】
void Print1(int arr[], int sz) { printf("Print1:\n"); for (int i = 0; i < sz; i++) { printf("%d\t", arr[i]); } } void Print2(int* arr, int sz) { printf("Print2:\n"); for (int i = 0; i < sz; i++) { printf("%d\t", arr[i]); } } void Print3(int(*p)[5],int sz) { printf("Print3:\n"); for (int i = 0; i < sz; i++) { printf("%d\t", *((*p)+i)); //printf("%d\t", (*p)[i]); } } int main() { int arr[5] = { 1,2,3,4,5 }; int sz = sizeof(arr) / sizeof(arr[0]); //写一个函数打印数组内容 //测试1: Print1(arr, sz); printf("\n"); //测试2: Print2(arr, sz); printf("\n"); //测试3: Print3(&arr,sz); return 0; }
4-5 这才是数组指针的正确使用方法捏【数组指针模拟打印二维数组】
指针数组虽然可以int(*p)[3]=&arr;其中arr是一个一维数组,但是这样太鸡肋了,
还不如直接int*p arr;
指针数组真正的使用场景是留给二维数组传数组名时,形参用指针数组接收。
void Print1(int arr[3][5], int row, int col) { printf("Print1:\n"); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("%d\t", arr[i][j]); } printf("\n"); } } void Print2(int(*p)[5], int row, int col) { printf("Print2:\n"); for (int i = 0; i < row; i++) { for (int j = 0; j < col; j++) { printf("%d\t", (* (p + i))[j]); //printf("%d\t", *(*(p+i)+j)); //printf("%d\t",p[i][j]); //p+i是第i行,也就是第i行整个数组的地址 //*(p+i)也就是对整个数组的地址解引用,就是第i行的数组名,也就是第i行首元素的地址 //*(p+i)+j就是第i行第j列元素的地址 //*(*(p+i)+j)也就是对第i行第j列元素的地址解引用,就是第i行第j列的元素 } printf("\n"); } } int main() { int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} }; //测试1: Print1(arr, 3, 5); printf("\n"); //测试2: Print2(arr, 3, 5); printf("\n"); return 0; }
上面目前讲的基本还是数组指针指向的是一个一维数组
其实数组指针还是可以指向一个二维数组:
int arr[3][5] = { {1,2,3,4,5},{2,3,4,5,6},{3,4,5,6,7} };
int(*p)[3][5]=&arr;
完结,撒花,等等,要不来一个小测试?
5 测试题和规律总结
测验1:
如果int(*arr[3])[5];
问题:怎么理解这个代码?
答案:数组指针数组
测验2:那么指针数组指针?
我总结的一点小规律
如果光要给上面这个东西命名的话,只用关注*和[]的出现次序排列就可以了
比如;数组指针数组:[]*[]
指针数组指针*[]*
然后再把[]存的内容和*指向的东西往里面填进去就可以了