博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二维数组和二级指针
阅读量:4552 次
发布时间:2019-06-08

本文共 2395 字,大约阅读时间需要 7 分钟。

对于如下程序

void fun(int **data,int row,int column){    for(int i = 0;i < row; ++ i)    {        for(int j = 0;j < column;++ j)            cout << data[i][j] << "\t";        cout << endl;    }}int main(){    int data[2][3] = {
{3,8,4},{4,5,6}}; fun(data,2,3); return 0;}

编译无法通过,提示“no known conversion from 'float [2][3]' to 'float **' for 1st argument”

如果在main函数中将data强制转换成二级指针,编译能通过,运行时发生段错误。
究其根本,是因为二维数组名,并不是一个二级指针。

二维数组

二维数组内存分配

一维数组名,数组首元素的地址,是一个指针。

二维数组是”数组的数组“,因而我们很容易产生二维数组名是一个二级指针的错觉,实际上并不是这样的。
屏幕快照 2016-09-04 下午5.29.19
如上图所示,实际上,不管是一维还是多维数组,都是内存中一块线性连续空间,因此在内存级别上,其实都只是一维。但是不同的定义使得表现形式不一样,从而有多维数组的概念。

访问数组元素其实非常简单,原因就在于元素在内存中的线性排列,这样对一维数组的访问只需要arr1[index] = *(arr1+index*sizeof(T));对二维数组的访问

arr2[i][j]=*(arr2+(i*col+j)*sizeof(T)),因此连续线性的数组访问效率很高。多维类似。

二维数组与数组指针

对于二维数组int data[2][3],可看做特殊的一维数组data[2],包含两个元素,每个元素的类型是int [3]。

无论如何,数组名总是代表数组首元素的地址,因此,二维数组名是一个数组指针,而非二级指针

那么到底什么是数组指针呢?

数组指针是一个指针,指向一个数组,数组指针的定义有如下形式

int data[2][3]int (*ptr)[3]ptr = data;//ptr指向data的第0行ptr = &data[1];//ptr指向data的第1行

数组指针的声明中,方括号中的维数指明了对应的指针变量偏移一个单位对应的内存偏移量。(如ptr + 1,ptr会向高地址移动3*4Byte)

上述声明中,圆括号不能省略,因为[]具有更高的有衔接,int *var[3]声明的是一个元素为int *的数组(指针数组)。

实际上,可用typedef 使得定义更简单易懂

typedef int int_array[3]; int_array *ptr = data;

因此,文章开头的程序中fun函数的定义改成如下形式才能够将二维数组data做为实参传入

void fun(int (*data)[3],int row,int column)void fun(int data[][3],int row,int column)

为什么不能将二维数组名强制转换成二级指针

void fun(int **data,int row,int column){    for(int i = 0;i < row; ++ i)    {        for(int j = 0;j < column;++ j)            cout << data[i][j] << "\t";        cout << endl;    }}int main(){    int data[2][3] = {
{3,8,4},{4,5,6}}; int** ptr = (int **)data; printf("%p,%p\n",ptr,data); printf("%p\n",ptr[0]); return 0;}

运行输出如下结果

屏幕快照 2016-09-04 下午8.03.26
ptr和data本质上都是指针,在赋值后,他们指向了同一片内存空间,如下图所示(每个数字为16进制中的一位,包含4bit,所使用测试机器为64位机器)
屏幕快照 2016-09-04 下午8.17.50
64位机器中,int占4个字节,int *占8个字节,因此ptr[0]就是data[0][0]和data[0][1]拼接起来的结果,故ptr[0]的值为0x800000003。可以看到,这个值并非data数组首元素的地址。因此当进行如下调用fun(ptr,2,3)时,试图访问的是0x800000003的未知空间,因此发生段错误。

二级指针和指针数组

对于如下程序

int *ptr_arr[2];    for(int i = 0;i < 2;++ i)    {        ptr_arr[i] = new int [3];        for(int j = 0;j < 3;++ j)            ptr_arr[i][j] = i + j;    }    fun(ptr_arr,2,3);

ptr_arr是一个元素为int *变量的数组(注意和数组指针声明的区别),是一个指针数组。

无论如何,数组名总是代表数组中首元素的地址。因此ptr_arr实际上是&ptr_arr[0],ptr_arr[0]是一个int *变量,因此,ptr_arr是指针的指针,也就是二级指针,这也是能够在fun函数中传入ptr_arr的原因。

也就是说,指针数组的数组名等价于一个二级指针

转载于:https://www.cnblogs.com/rainySue/p/er-wei-shu-zu-he-er-ji-zhi-zhen.html

你可能感兴趣的文章
二叉树_非递归先中后序_递归非递归求深度
查看>>
20181227 新的目标
查看>>
HDFS写流程
查看>>
生产环境服务器环境搭建+ 项目发布
查看>>
js按条件分类json数组,并合计同组数据(一维转换为二维)
查看>>
Exp6 信息搜集与漏洞扫描
查看>>
redis4安装
查看>>
随机生成双色球号码
查看>>
使用命令wsimport构建WebService客户端[转]
查看>>
第八遍:链接详解
查看>>
Qt5.5 使用smtp发邮件的各种坑
查看>>
js奇葩错误 字符串传递问题
查看>>
人之初,性本恶
查看>>
springboot 端口号
查看>>
使用AChartEngine画动态曲线图
查看>>
安卓项目五子棋代码详解(四)
查看>>
urllib 学习一
查看>>
bzoj4196 [Noi2015]软件包管理器——树链剖分
查看>>
kafka源码阅读环境搭建
查看>>
UI设计
查看>>