• 二维数组与二级指针是好朋友吗?


    抛出问题

    有一个二维数组,我想把它传给一个函数。于是我把函数接口定义出来了,如下:

    1. int array[2][3] = {1,2,3,4,5,6};
    2. void fun(int **array) {
    3. array[0][0] = 5;
    4. }

    当我试图直接把数组名传给函数时候,fun(array)编译会报错,大概意思就是类型不匹配。既然类型不匹配,那我就直接强转成你所需要的类型,于是我又做了调整,fun((int **)array),这下确实不报错了。但是此时我还没意识到问题的严重性。不出意外的情况下意外还是发生了,只要进入到这个函数后,程序就挂了。那你知道是什么原因吗?如果不清楚就往下看吧...

    指针

    先从指针说起,指针是一个特殊的变量, 它里面存储的数值被解释成为内存里的一个地址。要搞清一个指针需要搞清指针的四方面的内容:指针的类型、 指针所指向的类型 、 指针的值或者叫指针所指向的内存区、 指针本身所占据的内存区

    指针的类型

    只要把指针声明语句里的指针名字去掉,剩下的部分就是这个指针的类型。例如:

    1. int*ptr; //指针的类型是 int*
    2. char*ptr; //指针的类型是 char*
    3. int**ptr; //指针的类型是 int**
    4. int(*ptr)[3]; //指针的类型是 int(*)[3]

    指针所指向的类型

    只须把指针声明语句中的指针名字和名字左边的指针声明符*去掉, 剩下的就是指针所指向的类型。例如:

    1. int*ptr; //指针所指向的类型是 int
    2. char*ptr; //指针所指向的的类型是 char
    3. int**ptr; //指针所指向的的类型是 int*
    4. int(*ptr)[3]; //指针所指向的的类型是 int()[3]

    指针的值

    在32位程序里,所有类型的指针的值都是一个32位整数,因为32位程序里内存地址全都是32位长。

    指针本身所占用的内存大小

    意思是指针本身占了多大的内存,在32位平台里,指针本身占据了4个字节的长度。可以使用sizeof(指针的类型)测试。

    一维数组

    对于一个一维数组int array[10],数组名代表一个常量地址,该地址指向第一个元素。以下两种情况数组名不能当指针使用。

    &

    对数组名取址,int *p_array = &array,&这个运算符也很有讲究的,暂时不多说了。

    sizeof

    sizeof(array)计算的是整个数组在内存中所占用的空间。

    二维数组

    二维数组本质上是以数组作为数组元素的数组,即“数组的数组”。假设我们定义了一个二维数组int array[2][3] = {1,2,3,4,5,6}

    网上有很多地方都再说数组名arrayarray[0]&array[0]以及&array[0][0]是等效的。那我们代码测试一下。

    1. printf("%#x,%#x,%#x,%#x\r\n",array,array[0],&array[0],&array[0][0]);
    2. Terminal:
    3. 0x404008,0x404008,0x404008,0x404008

    因为这几种写法输出地址都是相同的,所以有的同学自然就认为这几种写法就是一样的。虽然地址相同,但是实际意义是有区别的,我们继续看下面的代码。

    1. //这里重新定义了指针变量,能够方便的知道右值得类型
    2. int *p_array1 = array[0];
    3. int *p_array2 = &array[0][0];
    4. int (*p_array3)[3] = &array[0];
    5. int (*p_array4)[3] = array;
    6. printf("%#X,%#X,%#X,%#X,%#X\r\n",array,++p_array1, ++p_array2, ++p_array3, ++p_array4);
    7. Terminal:
    8. 0X404008,0X40400C,0X40400C,0X404014,0X404014

    根据以上实验分析能够看出:array[0]&array[0][0]指针类型相同,都是int *,地址存放的是int数据,当指针自增1时地址都偏移了一个int类型的大小。

    &array[0]array指针类型相同,都是int (*)[3],首先它是一个数组指针,这个指针指向一个数组,数组中数据的类型为int型。当指针自增1时地址都偏移了一个数组的长度(即3个int数据的大小)。

    所以说array只和&array[0]真正意义等效。那怎么去理解这几种表达呢 ?

    表示

    含义
    array是一个数组指针,类型为int (*)[3]。指向二维数组中第一个元素(元素是一维数组),指针所指向的内存大小为一维数组的长度
    array[0]是一个指针,类型为int *。就相当于一个一维数组名,指向一维数组中第一个元素的地址,指针所指向的内存大小为一个数据长度
    &array[0]是一个数组指针,类型为int (*)[3]。相当于对一维数组取地址。指针所指向的内存大小为一维数组的长度
    &array[0][0]是一个指针,类型为int *,是对二维数组中第一个数据取地址,注意是数据不是元素,指针所指向的内存大小为一个数据长度

    如以上能够理解清楚,那么文中的问题应该就能够自己分析清楚了。

    二级指针

    先定义一个二级指针int **p,首先p是一个指针,在这个地址中存放的数据是指向一个整形数据的地址。

    问题解答

    接着看文章中的问题,把一个二维数组强转成二级指针传给了函数。注意二维数组名的类型是一个数组指针二级指针完全不是一个东西。那么会出现什么问题呢?

    1. int array[2][3] = {1,2,3,4,5,6};
    2. int main(int argc ,char **argv) {
    3. int **p_data = (int **)array;
    4. printf("%#x, %d\r\n", p_data, *p_data);
    5. }
    6. Terminal:
    7. 0x404008, 1
    地址数据
    0x4040081
    0x40400C2
    0x4040103
    0x4040144
    0x4040185
    0x40401C6

    看上面的例子,array的地址为0x404008,当把一个二维数组强转成二级指针的时候。p_data地址中存放的数据为1,因为二维数据中第一个数据就是1。根据二级指针的定义,这个数据1又会当成一个地址,该地址指向的内存才是最终的数据。

    但是呢,这个地址1其实是个数据,并不是真正的地址。如果访问地址1中的数据,就属于非法访问地址了,可能会进入异常。

    二维数据当函数入参

    通过以上学习我们已经知道二维数组名就是一个数组指针,我们函数就可以像下面这样声明。

    1. void fun(int array[][3], int row);
    2. void fun(int (*p_array)[3], int row);
    3. void fun(int row, int column, int array[row][column]);

    实参与入参

    最后在看下,应该如何定义与实参相对应的形参的数据类型。

    含义实参形参
    二维数组(数组的数组)int array[4][6]int (*array)[6]
    指针数组(数组中的数据是指针)int *array[6]int **array
    数组指针(指向数组的指针)int (*array)[6]int (*array)[6]
    二级指针(指针的指针)char **arraychar **array

    点击链接加入群聊【C语言/C++编程学习基】:小鱼快来啊的个人空间-小鱼快来啊个人主页-哔哩哔哩视频哔哩哔哩小鱼快来啊的个人空间,提供小鱼快来啊分享的视频、音频、文章、动态、收藏等内容,关注小鱼快来啊账号,第一时间了解UP注动态。编程学习群:724050348 每天分享一个编程小游戏~C/C++游戏源码素材及各种安装包, 私信不常看!https://space.bilibili.com/1827181878?spm_id_from=333.1007.0.0

  • 相关阅读:
    nginx模块
    用springsecurity去代替拦截器
    面试时,公司的什么表现让你一看就知道不靠谱?
    《C和指针》笔记34:字符串函数
    无线耳机什么质量好?音质较高的无线蓝牙耳机盘点
    web前端大作业 (仿英雄联盟网站制作HTML+CSS+JavaScript) 学生dreamweaver网页设计作业
    软件安装攻略:EmEditor编辑器下载安装与使用
    PID算法
    [陇剑杯2021] 复现
    租用香港服务器您需要知道的5件事
  • 原文地址:https://blog.csdn.net/yx5666/article/details/128039210