二维数组和指针(C语言)
二维数组和指针
|
二维数组和指针1、二维数组和数组元素的地址若有以下定义:int *p, a[3][4];
1)二维数组a由若干个一维数组组成在C语言中定义的二维数组实际上是一个一维数组,这个一维数组的每一个成员又是一个一维数组。如以上定义的a数组,则可视a数组由a[0]、a[1]、a[2]等三个元素组成,而a[0]、a[1]、a[2]等每个元素又分别是由4个整型元素组成的一维数组。可用a[0][0]、a[0][1]等来引用a[0]中的每个元素,其它依次类推。在第二节中已解释过,C语言中,在函数体中或在函数外部定义的一维数组名是一个地址常量,其值为数组第一个元素的地址,此地址的基类型就是数组元素的类型。在以上二维数组中,a[0]、a[1]、a[2]都是一维数组名,同样也代表一个不可变的地址变量,其值依次为二维数组每行第一个元素的地址,其基类型就是数组元素的类型。因此,对于二维数组,象a[0]++这样的表达式是非法的。若有表达式a[0]+1,表达式中1的单位应当是2个字节。在以上定义中,指针变量p的基类型与a[i](0≤i<3)相同,因此,赋值语句p=a[i];是合法的。我们已知a[i]也可以写成:*(a+i),故以上赋值语句也可写成:p=*(a+i);。
2)二维数组名也是一个地址常量二维数组名同样也是一个存放地址常量的指针,其值为二维数组中第一个元素的地址。以上a数组,数组名a的值与a[0]的值相同,只是其基类型为具有4个整型元素的数组类型。即a+0的值与a[0]的值相同,a+1的值与a[1]的值相同,a+2的值与a[2]的值相同,它们分别表示a数组中第零、第一、第二行的首地址。二维数组名应理解为一个行指针。在表达式a+1中,数值1的单位应是4×2个字节,而不是2个字节。赋值语句p=a;是不合法的,因为p和a的基类型不同。同样,对于二维数组名a,也不可以进行a++,a=a+i等运算。
3)二维数组元素的地址二维数组元素的地址可以由表达式&a[i][j]求得;也可以通过每行的首地址来表示。以上二维数组a中,每个元素的地址可以通过每行的首地址:a[0]、a[1]、a[2]等来表示。如:地址&a[0][0]可以用a[0]+0来表示,地址&a[0][1]可以用a[0]+1表示;若0≤i<3、0≤j<4,则a[i][j]的地址可用以下五种表达式求得:(1)&a[i][j](2)a[i]+j(3)*(a+i)+j(4)&a[0][0]+4*i+j (5)a[0]+ 4*i+j
在以上表达式中a[i]、&a[0][0]、a[0]的基类型都是int类型,系统将自动据此来确定表达式中常量1的单位是2个字节。但是不可以把求a[i][j]地址的表达式写成:a+4*i+j,因为a的基类型是4个整型元素的数组类型,系统将自动据此来确定常量1的单位是8个字节。
2、通过地址来引用二维数组元素若有以下定义:int a[3][4],i,j;且当0≤i<3、0≤j<4,则a数组元素可用以下五种表达式来引用:
(1)a[i][j](2)*(a[i]+j)(3)*(*(a+i)+j)(4)(*(a+i))[j](5)*(&a[0][0]+4*i+j)
在(2)中,表达式*(a[i]+j)中,因为a[i]的基类型为int,j的位移量为2×j字节。
在(3)中,表达式*(*(a+i)+j)中,a的基类型为4个元素的数组,i的位移量为4×2×i字节;而*(a+i)的基类型为int,j的位移量仍为2×j字节。
在(4)中,*(a+i)外的一对圆括号不可少,若写成:*(a+i)[j],因为运算符[]的优先级高于*号,表达式可转换成:*(*(a+i)+j)),即为:*(*(a+i+j)),这时i+j将使得位移量为4×2×(i+j)个字节,显示然这已不是元素a[i][j]的地址。*(*(a+i+j))等价于*(a[i+j])、等价于:a[i+j][0],引用的是数组元素a[i+j][0],而不是a[i][j],很可能早已超出数组定义的范围。
在(5)中,&a[0][0]+4*i+j代表了数组元素a[i][j]的地址,通过间址运算符*号,表达式*(&a[0][0]+4*i+j)代表了数组元素a[i][j]的存储单元。
3、通过建立一个指针数组来引用二维数组元素若有以下定义:int *p[3], a[3][2], i,j ;在这里,说明符*p[3]中,也遵照运算符的优先级,一对[]的优先级高于*号,因此p首先与[]结合,构成p[3],说明了p是一个数组名,系统将为它开辟3个连续的存储单元;在它前面的*号则说明了数组p是指针类型,它的每个元素都是基类型为int的指针。若满足条件:0≤i<3,则p[i]和a[i]的基类型相同,p[i]= a[i]是合法的赋值表达式。
若有以下循环:for(i=0; i<3; i++) p[i]= a[i];在这里,赋值号右边的a[i]是常量,表示a数组每行的首地址,赋值号左边的p[i]是指针变量,循环执行的结果使p[0]、p[1]、p[2]分别指向a数组每行的开头。这时,数组p和数组a之间的关系如图9.6所示。
当p数组的每个元素指向a数组每行的开头时,则a数组元素a[i][j]的引用形式*(a[i]+ j)和*(p[i]+j)是完全等价的。由此可见,这时可以通过指针数组p来引用a数组元素,它们的等价形式如下:(1)*(p[i]+j) (2)*(*(p+i)+j) (3)(*(p+i))[j] (4)p[i][j] 不同的是:p[i]中的值是可变的,而a[i]中的值是不可变的。
通过建立一个行指针来引用二维数组元素若有以下定义:int a[3][2], (*prt)[2];在这里,说明符(*prt)[2]中,由于一对圆括号的存在,所以*号首先与prt结合,说明prt是一个指针变量,然后再与说明符[2]结合,说明指针变量prt的基类型是一个包含有两个int元素的数组。在这里,prt的基类型与a的相同,因此prt=a;是合法的赋值语句。prt+1等价于a+1、等价于a[1]。当prt指向a数组的开头时,可以通过以下形式来引用a[i][j]:(1) *(prt[i]+j) (2) *(*(prt+i)+j) (3)(*(prt+i))[j] (4) prt[i][j] 在这里,prt是个指针变量,它的值可变,而a是一个常量。
附:
#include "stdio.h"
void disp(int (*a)[3])
{
printf("%d",*(*(a+1)+1));
}
void main()
{
int a[2][3];
a[0][0]=1;
a[0][1]=2;
a[0][2]=3;
a[1][0]=4;
a[1][1]=5;
a[1][2]=6;
disp(&a[0]);//也可以写作disp(a);
}
二维数组和指针(C语言)的更多相关文章
- 关于c语言二维数组与指针的个人理解及处理办法。
相信大家在学习C语言时,对一维数组和指针的理解应该是自信的,但是,我在学习过程中,看到网上一些博文,发现即便是参加工作的一些专业编程人员,突然碰到二维数组和指针的问题时,也可能会遇到难以处理的诡异问题 ...
- C语言 二维数组(指针)动态分配和释放(转)
C 二维数组(指针)动态分配和释放 先明确下概念: 所谓32位处理器就是一次只能处理32位,也就是4个字节的数据,而64位处理器一次就能处理64位,即8个字节的数据.如果我们将总长128位的指令分别按 ...
- 程序员之--C语言细节13(二维数组和指针,&*a[i][0]的理解,数组1[e]和e[1]非常可能你没见过)
主要内容:二维数组和指针.&*a[i][0]的理解.数组1[e]和e[1] #include <stdio.h> #define NUM_ROWS 10 #define NUM_C ...
- C语言教学--二维数组和指针的理解
对于初学者对二维数组和指针的理解很模糊, 或者感觉很难理解, 其实我们和生活联系起来, 这一切都会变得清晰透彻. 我们用理解一维数组的思想来理解二维数组, 对于一维数组,每个箱子里存放的是具体的苹果, ...
- c语言编程-----指向二维数组的指针
c中如何返回一个指向二维数组的指针 #include <stdio.h> #include <stdlib.h> #define COUNT 3 typedef int (*M ...
- 对二维数组使用指针进行操作的探索(C语言)
/* Name: 对二维数组使用指针进行操作的探索 Copyright: Author: lingr7 Date: 01/12/18 11:55 Description: */ #include< ...
- C/C++——二维数组与指针、指针数组、数组指针(行指针)、二级指针的用法
本文转载自:https://blog.csdn.net/qq_33573235/article/details/79530792 1. 二维数组和指针 要用指针处理二维数组,首先要解决从存储的角度对二 ...
- C指针 指针和数组 二维数组的指针 指针应用
直接到变量名标识的存储单元中读取变量的值--直接寻址 通过其他变量间接找到变量的地址读取变量的值--间接寻址 指针变量存放地址 显示变量的地址 指针变量使用前必须初始化,若不知指向哪,可先指向NULL ...
- C++笔记-数组指针/二维数组转换指针
参考资料: 1. 作者 BensonLaur :https://www.cnblogs.com/BensonLaur/p/6367077.html 2. https://blog.csdn.net/ ...
随机推荐
- PROFIBUS-DP现场总线的结构及应用
PROFIBUS的最大优点在于具有稳定的国际标准EN50170作保证,并经实际应用验证具有普遍性.目前已广泛应用于制造业自动化.流程工业自动化和楼宇.交通电力等领域. PROFIBUS由3个兼容部分组 ...
- 弱智python小游戏猜数字
from random import randintnum = randint(0,100)print("Guess what I think:?")bingo = Falsewh ...
- 斑马条码打印机GK888T打印标签是间隔的 ,不是连续的
有间断的标签纸和连续的标签纸是两种不同的纸张类型, 打印机的标签感应器需要工作在不同的模式来跟踪感应它们. 打印机正确感应纸张才不会红灯闪烁,打印的内容才按文件设计打印到标签的对应位置上. 所以要在驱 ...
- php手册 | python手册 | perl手册 | c#.net手册 | c++手册 | ruby手册 | jquery手册 | js手册 | prototype手册 | mysql手册 | smarty手册 | css手册 | html手册 | nginx手册 | apache手册 | shell手册 | svn手册
收集各种实用类手册: http://shouce.jb51.net/shell/
- 通过jmap查看jvm采用的垃圾收集器
1 tomcat 的PID获得 ps -ef|grep tomcat [root@iZ2zeapch8kbaw4bxnz8vxZ tomcat7]# ps -ef|grep tomcat root ...
- java将字符串存入GridF并通过id或文件名查询
import static org.bson.codecs.configuration.CodecRegistries.fromProviders; import static org.bson.co ...
- THUWC2017颓废记
2.9翘掉Wc闭幕式,和石家庄大爷们坐一辆车去杭州…路上日常orz gzz.2.10早上来报到,拍照.宿舍里另外四个人都是GD大爷.开幕式是喜闻乐见的thu日常黑pku(“在中国,世界一流大学有两所, ...
- https和http/2
http://geek.csdn.net/news/detail/188003 HTTPS协议原理分析 HTTPS协议需要解决的问题 HTTPS作为安全协议而诞生,那么就不得不面对以下两大安全问题: ...
- 【刷题】BZOJ 3262 [HNOI2008]GT考试
Description 阿申准备报名参加GT考试,准考证号为N位数X1X2....Xn(0<=Xi<=9),他不希望准考证号上出现不吉利的数字. 他的不吉利数学A1A2...Am(0< ...
- 【BZOJ4205】卡牌配对
Description 现在有一种卡牌游戏,每张卡牌上有三个属性值:A,B,C.把卡牌分为X,Y两类,分别有n1,n2张. 两张卡牌能够配对,当且仅当,存在至多一项属性值使得两张卡牌该项属性值互质,且 ...