指针和数组--指针和二维数组的关系

news/2024/11/27 8:37:35/

指针和二维数组的关系

目录

一、二维数组的行地址和列地址

二、通过二维数组的行指针和列指针来引用二维数组元素


一、二维数组的行地址和列地址

        在C语言中,可将一个二维数组看成是由若干个一维数组构成的。例如若有下面的定义: 

 int a[3][4]; 

则,其二维数组的逻辑存储结构如下图所示: 

可通过下图来理解二维数组的行地址和列地址的概念。首先可将二维数组a看成是由a[0]、a[1]、a[2]三个元素组成的一维数组,a是它的数组名,代表其第一个元素a[0]的地址(&a[0])。根据一维数组与指针的关系可知,a+1表示的是首地址所指元素后面的第1个元素地址,即元素a[1]的地址(&a[1])。同理,a+2表示元素a[2]的地址(&a[2])。于时,通过这些地址就可以引用个元素的值了,例如*(a+0)或*a即元素a[0],*(a+1)即为元素a[1],*(a+2)即为元素a[2]。注意:这里所谓的元素事实上仍然是个地址,并非具体的数值。

其次,可将a[0]、a[1]和a[2]三个元素分别看成是由4个整型元素组成的一维数组的数组名。例如,a[0]可以看出是由元素a[0][0]、a[0][1]、a[0][2]和a[0][3]这4个整型元素组成的一维数组的数组名,代表该一维数组的第一个元素a[0][0]的地址(&a[0][0]),a[0]+1则代表元素a[0][1]的地址(&a[0][1])。因此,*(a[0]+0)即为元素a[0][0],*(a[0][1])即为元素a[0][1]。

注意:由于a[0]可以看出是由4个整形元素组成的一位数组的数组名。因此,a[0]+1中的数字1代表的是一个整型元素所占的存储单元的字节数,即二维数组的一列所占的字节数:1×sizeof(int);而a可看成由a[0]、a[1]、a[2]三个元素组成的一维数组的数组名,因此表达式a+1中的数字1代表的是一个含有4个整型元素的一维数组所占的存储单元的字节数,即二维数组的一行所占的字节数:4×sizeof(int)。

        根据上面分析可归纳如下:a[i]即*(a+i)可以看出是一维数组a的下标为i的元素,同时,a[i]即*(a+i)又可看成是由a[i][0]、a[i][1]、a[i][2]和a[i][3]等4个元素组成的一维整型数组的数组名,代表这个一维数组第1个元素a[i][0]的地址(&a[i][0]);而a[i]+j即*(a+i)+j代表这个数组中下标为j的元素的地址,即&a[i][j]。*(a[i]+j)即*(*(a+i)+j)就代表这个地址所指向的元素的值,即a[i][j]。因此,下面4种表示a[i][j]的形式是等价的。

a[i][j]-------*(a[i]+j)---------*(*(a+i)+j)----------(*(a+i))[j]

        如果将二维数组的数组名a看成一个行地址(第0行的地址),则a+i代表二维数组a的第i行的地址,a[i]可看成一个列地址,即第i行第0列的地址。行地址a每次加1,表示指向下一行,而列地址a[i]每次加1,表示指向下一列。

        打个比方,二维数组的行地址好比一个宾馆房间所在的楼层号,二维数组的列地址好比一个宾馆房间所在的房间号,要想进入第i层的第j个房间,必须先从第1层开始登楼梯,登到第i层后,在从第i层的第1个房间开始数,直到数到第j个房间为止。

二、通过二维数组的行指针和列指针来引用二维数组元素

        通过对二维数组的行地址和列地址的分析可知,二维数组中有两种指针。一种是行指针,使用二维数组的行地址进行初始化;另一种是列指针,使用二维数组的列地址进行初始化。

        例如,对于上图所示的二维数组a,可定义如下的行指针:

         int (*p)[4];

        在解释变量声明语句中变量的类型时,虽然说明符[ ]的优先级高于* ,但由于圆括号的优先级更高,所以先解释* ,在解释[   ] 。所以,p的类型被表示为

p-----------> * ---------------> [4] ------------>int

说明定义了一个可指向含有4个元素的一维整型数组的指针变量。关键字int代表行指针所指一维数组的类型。[ ] 中的4表示指针所指一维数组的长度,它是不可以省略的。实际上,这个指针变量p可作为一个指向二维数组的行指针,它所指向的二维数组的每一行都有4个元素。

注意:在变量声明语句中必须显式地指定指针变量所指向的一维数组的长度(对应于二维数组的列数)。对指向二维数组的行指针p仅从初始化的方法为:p = a;或 p = &p[0];

        通过行指针p引用二维数组a的元素a[i][j]的方法可用以下4种等价的形式:

p[i][j]<----------> *(p[i]+j)<----------> *(*(p+i)+j)<---------->(*(p+i))[j]

        由于列指针所指向的数据类型为二维数组的元素类型,因此列指针和指向同类型简单变量的指针的定义法是一样的。例如,对于上图的二维数组a,可定义下列指针:

int *p;

p=a[0];    p=*a;   p =&a[0][0];

定义了列指针p后,为了能通过p引用二维数组a的元素a[i][j],可将数组a看成一个由(m行×n列)个元素组成的一维数组。由于p代表数组的第0行0列的地址,而从数组的第0行第0列寻址到数组的第i行第j列,中间需跳过i×n+j个元素,因此,p+i*n+j代表数组的第i行第j列的地址,即&a[i][j],*(p+i*n+j)都表示a[i][j]。

注意:此时不能用p[i][j]来表示数组元素,这是因为此时并未将这个数组看出二维数组,而是将二维数组等同于一维数组看待的,也就是将其看成了一个具有mXn个元素的一维数组。正因如此,在定义二维数组的列指针时,无须指定他所指向的二维数组的列数。

例题:编写程序,输入一个3行4列的二维数组,然后输出这个二维数组的元素值。

#include <stdio.h>#define N 4void InputArray(int p[][N],int m,int n);
void OutputArray(int p[][N],int m,int n);
int main(void)
{int a[3][4];printf("Input 3*4 numbers:\n");InputArray(a,3,4);OutputArray(a,3,4);return 0;
}void InputArray(int p[][N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){scanf("%d",&p[i][j]);}}
}void OutputArray(int p[][N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++){printf("%4d",p[i][j]);}printf("\n");}
}

#include <stdio.h>#define N 4void InputArray(int (*p)[N],int m,int n);
void OutputArray(int (*p)[N],int m,int n);
int main(void)
{int a[3][4];printf("Input 3*4 numbers:\n");InputArray(a,3,4);OutputArray(a,3,4);return 0;
}void InputArray(int (*p)[N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++)scanf("%d",*(p+i)+j);}
}void OutputArray(int (*p)[N],int m,int n)
{int i,j;for(i=0;i<m;i++){for(j=0;j<n;j++)printf("%4d",*(*(p+i)+j));}
}

 


http://www.ppmy.cn/news/483686.html

相关文章

虚拟机ubuntu18.04及CentOS7安装VMware-tool问题解决

一、centos7 安装VMware-tool工具选项为黑色&#xff1a;https://blog.csdn.net/weixin_45158066/article/details/123268884 打开虚拟机&#xff0c;将VMware-tool系统分区的文件复制到虚拟机文件分区,如/home/huangqifa/VMware-tool 从以上目录打开终端&#xff0c;tar -x…

VUE2后台管理系统--权限管理、按钮管理

1、做法 在项目接手时候想的还是根据花裤衩大佬的方法进行&#xff0c;后端返回异步路由进行加载。后来和后端一起确认并且查阅了其他项目做法后&#xff0c;采用的是所有路由在前端的异步路由中进行对比查找赋值&#xff0c;再通过动态路由添加。 2、思路 在用户进行登录时…

python:使用Scikit-image中的滤波函数对遥感影像做空间滤波(中值,高斯,Sobel,Laplace,Scharr等)

作者:CSDN @ _养乐多_ 本文将介绍使用Scikit-image中的滤波函数对遥感影像做空间滤波的代码。滤波方法包括:中值滤波器,高斯滤波器,Sobel滤波器,Laplace滤波器,Scharr滤波器等。并将原始影像和结果影像绘制成图。 结果如下图所示, 文章目录 一、空间滤波函数详解二、…

ipad吃鸡用什么蓝牙耳机?高性价比无线蓝牙耳机品牌

如今蓝牙耳机品牌泛滥&#xff0c;溢价严重&#xff0c;要如何挑选适合自己的蓝牙耳机呢&#xff1f;有没性价比高&#xff0c;口碑好的蓝牙耳机呢&#xff1f;今天给大家推荐几款性价比高性能好的蓝牙耳机&#xff0c;口碑&#xff0c;使用感受都非常不错。 一、南卡Lite Pro…

如何选一款支持iPadh和拯救者R7000的有线耳机

iPad Air 4 和 最近的几款Pro机型都有type- C接口 拯救者R7000也配有一个type- C口 但是常常发现不是每个type- C耳机都是插上去就能用的 查了一下资料&#xff0c;发现网上很多人都说只有华为送的耳机可以。 但价格感人。。而且还常常缺货 所以&#xff0c;深挖了一番&#xf…

ipad吃鸡用什么耳机好?低延迟性价比高的蓝牙耳机推荐

在科技发展下&#xff0c;我们的生活也变得科技起来&#xff0c;如今也越来越多的人不再选择传统的有线耳机了&#xff0c;而是选择了高大上的蓝牙耳机&#xff0c;不管是运动中听音乐、还是上下班路上&#xff0c;戴上蓝牙耳机更显的方便。那市场上什么牌子的蓝牙耳机好你知道…

最长回文子串

给定一个字符串 s&#xff0c;找到 s 中最长的回文子串。你可以假设 s 的最大长度为1000。 示例 1&#xff1a; 输入: “babad” 输出: “bab” 注意: "aba"也是一个有效答案。 示例 2&#xff1a; 输入: “cbbd” 输出: “bb” class Solution:def longestPalind…

前后端传值不区分大小写

在大多数编程语言和技术中&#xff0c;前端和后端传递的值是区分大小写的。大小写敏感性意味着变量名、对象属性或其他标识符的大小写必须精确匹配才能正确传递和识别值。 然而&#xff0c;有些编程语言或框架在处理传值时可以进行不区分大小写的比较。这通常是通过特定的配置…