指针进阶II · 指针数组和数组指针 您所在的位置:网站首页 数组指针是二级指针吗 指针进阶II · 指针数组和数组指针

指针进阶II · 指针数组和数组指针

#指针进阶II · 指针数组和数组指针| 来源: 网络整理| 查看: 265

大家好,我是安然无虞。 文章目录一、指针数组

补充易错点

二、数组指针

补充易错点

三、遇见安然遇见你,不负代码不负卿。

一、指针数组

指针数组,顾名思义就是存放指针的数组

看看下面这些类型的数组:

int* arr1[10];//整型指针的数组 char* arr2[5];//一级字符指针的数组 char** arr3[5];//二级字符指针的数组

下面给出一道指针数组的小例题:

#include 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; }

image

很简单,这里就不过多阐述了。

补充易错点

&数组名和数组名:

之前有提到过这部分概念,所以在这里就不过多赘述了,直接给出下面结论:&数组名表示取出整个数组的地址;数组名表示数组首元素的地址。,因为 &数组名+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 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 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 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 //一般实参是一级指针的时候,形参写成一级指针即可,不需要写成数组的形式 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 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);

三、遇见安然遇见你,不负代码不负卿。

image



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有