大家好,我是安然无虞。
文章目录
一、指针数组
指针数组,顾名思义就是存放指针的数组
看看下面这些类型的数组:
int* arr1[10];//整型指针的数组 char* arr2[5];//一级字符指针的数组 char** arr3[5];//二级字符指针的数组
下面给出一道指针数组的小例题:
#include<stdio.h> int main() { char* arr[] = { "abcdef", "qwer", "zhangsan" }; int sz = sizeof(arr) / sizeof(arr[0]); int i = 0; for (i = 0; i < sz; i++) { printf("%s\n", arr[i]); } return 0; }
很简单,这里就不过多阐述了。
补充易错点
&数组名和数组名:
之前有提到过这部分概念,所以在这里就不过多赘述了,直接给出下面结论:&数组名表示取出整个数组的地址;数组名表示数组首元素的地址。,因为 &数组名+1 跳过整个数组,数组名+1 却仅仅跳过一个首元素(这里细细体会一下)。
二、数组指针
问:数组指针是数组还是指针?
答案:数组指针是指针,是能够指向数组的指针。
试分析以下代码:
int* p1[10];//p1是存放10个整型指针的数组 int(*p2)[10];//p2先和'*'结合,说明p2是一个指针,指向的是一个数组,数组有10个元素,每个元素类型是int,所以p2是一个数组指针
这里的话我就直接把答案给出来了,不过需要注意的是:[ ] 的优先级要高于 * 的,所以在写数组指针的时候必须加上 () 来保证 p2 先和 * 结合。
为了强化理解上述概念,做了如下补充:
char arr[5]; char(*pa)[5] = &arr;//pa先和*结合,说明pa是一个指针,看到'[]'说明指向一个数组,数组有5个元素,每个元素类型是char,所以pa的类型就是char(*)[5] int* parr[6]; int*(*pa)[6] = &parr;//pa类型是int*(*)[6]
到这里还是得探讨一下,数组名arr 和&数组名&arr 的本质是什么?
int arr[10]; //arr类型是int*(整型指针) //&arr类型是int(*)[10](数组指针)
既然数组指针指的是数组,那么数组指针中存放的就是数组的地址。
问:数组指针是怎么使用的呢?
请看下列代码:
#include<stdio.h> void print_arr1(int arr[3][5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } void print_arr2(int(*arr)[5], int row, int col) { int i = 0; for (i = 0; i < row; i++) { int j = 0; for (j = 0; j < col; j++) { printf("%d ", arr[i][j]); } printf("\n"); } } //*(arr+i)相当于二维数组第i行的数组名(可以这么去理解:*和&相抵消) //数组名相当于数组首元素的地址,其实也就是第i行第一个元素的地址 //*(*(arr + i) + j) //(arr + i) 相当于 第i行数组的地址 //*(arr + i) 相当于 第i行数组名,也就是第i行首元素的地址 //(*(arr + i) + j) 相当于 第i行第j列元素的地址 //*(*(arr + i) + j) 相当于 第i行第j列的元素 int main() { int arr[3][5] = { 1,2,3,4,5,6,7,8,9,10 }; print_arr1(arr, 3, 5); print_arr2(arr, 3, 5); //数组名arr表示首元素的地址 //但是二维数组的首元素跟一维数组不同,二维数组的首元素是第一行 //所以这里传递的arr,其实相当于第一行的地址,属于一维数组的地址 //所以可以用数组指针接收 return 0; }
学完数组指针和指针数组,分析下列代码:
int arr[5];//arr是一个数组,数组有5个元素,每个元素是int类型 int* parr1[10];//parr1是一个数组,数组有10个元素,每个元素类型是int* int(*parr2)[10];//parr2是一个指针,指向一个含有10个元素,元素类型是int的数组,所以parr2是一个数组指针 int(*parr3[10])[5]; //parr3先和[]结合,说明parr3是一个数组,数组有10个元素,每个元素的类型是int(*)[5]的指针,该指针指向一个含有10个整型元素的数组 //所以parr3是一个数组指针数组
好,说到这里再啰嗦一下,对数组指针做一个总结:
int arr[10]; int* p = arr; int(*p2)[10] = &arr;//取出的是整个数组的地址,既然是数组的地址 //就应该放到数组指针里面去,所以p2就是一个数组指针 //对p,p2进行分析: //p中存放的是首元素的地址 //p+1跳过一个int //*p访问一个int数据-4个字节,*p等价于首元素 //p2存放的是arr数组的地址 //p2+1跳过整个数组 //*p2访问的是arr数组,*p等价于arr(可以理解为&和*抵消了) //那么*p2就是数组名了,所以*p2本质就是arr数组首元素的地址 //p <=> *p2 <=> arr //p+1 <=> *p2 + 1
补充易错点
我们在写代码的时候难免要把【数组】或者【指针】传递给函数,那么函数的参数应该怎么设计呢?
一维数组传参
#include<stdio.h> void test(int arr[]);//ok - 数组传参时,形参部分不会真的创建一个数组,写成数组是为了方便我们理解,写成指针才是本质 void test(int arr[10]);//ok void test(int* arr);//ok void test2(int* arr[20]);//ok void test2(int** arr);//ok int main() { int arr[10] = { 0 }; int* arr2[20] = { 0 }; test(arr);//数组名相当于首元素的地址 test2(arr2); return 0; }
一维数组传参比较简单,在这里的话就不过多赘述了,下面看看二维数组传参
二维数组传参
#include<stdio.h> void test(int arr[3][5]);//ok void test(int arr[][]);//这种写法是错误的,因为二维数组传参行可以省略,但是列不能省略 //因为列表示一行有几个元素,如果不知道一行有几个元素,那么这一行访问完了,不知道下一行在哪(细品) void test(int arr[][5]);//ok void test(int* arr);//这种写法是错误的,形参部分应该用数组指针接收 void test(int* arr[5]);//这种写法是错误的,误写成指针数组了 void test(int(*arr)[5]);//ok void test(int** arr);//错错错 int main() { int arr[3][5] = { 0 }; test(arr);//数组名表示首元素的地址,二维数组的首元素是第一行,所以二维数组的数组名表示的是第一行的地址 //故而形参部分需要用数组指针接收 return 0; }
一级指针传参
#include<stdio.h> //一般实参是一级指针的时候,形参写成一级指针即可,不需要写成数组的形式 void print(int* arr, int n) { int i = 0; for (i = 0; i < n; i++) { printf("%d ", arr[i]); } printf("\n"); } int main() { int arr[10] = { 1,2,3,4,5,6,7,8,9 }; int* p = arr; int sz = sizeof(arr) / sizeof(arr[0]); //一级指针p,传给函数 print(p, sz); return 0; }
思考题:
当一个函数的形参是一级指针的时候,函数能接受什么参数?
比如下面的test函数:
void test2(char** p);
问:test函数能接收什么参数?
大家一定要想清楚,如果给你这么一个函数,我们可以把什么样的参数给它传过去,因为这点很重要!
请看:
int a = 10; int* ptr = &a; int arr[10] = {0}; test(&a); test(ptr); test(arr);
二级指针传参
#include<stdio.h> void test(int** ptr) { printf("num = %d\n", **ptr); } int main() { int n = 10; int* p = &n; int** pp = &p; test(&p); test(pp); return 0; }
思考题:
当一个函数的形参是二级指针的时候,函数能接受什么参数?
比如下面的test2函数:
void test2(char** p);
请看:
char ch = 'w'; char* pc = &ch; char** ppc = &pc; char* arr[10] = {0}; test(&pc); test(ppc); test(arr);
三、遇见安然遇见你,不负代码不负卿。