二维数组和指针
2016-05-18 16:58
337 查看
0.
关于C语言的指针,我觉得真正难的是:当指针和二维数组掺和起来的时候,太令人肾疼了。如果你不是很清楚一维指针,不要看这篇文章!!!这篇文章中写的都是我对二维数组和指针的理解,并没有真正可靠的出处。1.正式开始
对二维数组(int a[3][4])的理解(0). 二维数组中有很多看起来一样,但所包含的意义不一样的东西,煞是蛋疼,注意区分。
(1). 从二维数组的角度来看,a代表二维数组首元素的地址,
对二维数组来说,它的首元素不是一个简单的元素了,而是由4个整型元素构成的一维数组。 (这个时候把一维数组看成一个元素)
所以a是第一个一维数组的地址,a+1是第二个一维数组的地址。
(2). 二维数组可以理解为数组的数组,把每一行看成一个一维数组。
a是二维数组名,a中有3行,即3个行元素,a[0],a[1],a[2],每一个行元素是一个一维数组。
所以可以把a[0]理解为一个一维数组的数组名(也就是这个一维数组的首元素地)。
那么a[0]+1是二维数组0行1列的那个元素的地址,a[0]与&a[0][0]等价,a[0]+1与&a[0][1]等价就很容易理解了。(在一维数组的层面去理解上面的问题)
特别注意:在二维数组a中,a[i]不代表某一元素的值,它代表的是一个一维数组名。
(3). 如果像(2).那样,把二维数组看成一维数组(a[3])。
它的第一个元素是a[0],我们可以通过a[0]或者通过指针的方式去访问第一个元素*(a+0)。
所以*(a+1)和a[1]是等价的。都是访问a[1]这个元素的。这一点也就很容易理解了。
a[0]也是一个一维数组(假设为n[4]),
所以把*(a+0)或者a[0]理解为这个一维数组的数组名n(也就是这个一维数组的首元素地址)。
*(a+0)+1就是n这个一维数组的第二个元素的地址。
(4). 在指向行的指针前面加一个*,就转换成了指向列的指针。
例如,a和a+1是指向行的,前面加个*就是指向列的了
反之,在指向列的指针前面加上&,就变成指向行的了。
例如,a[0]是指向0行0列元素的指针,在它的前面加上一个&,得到&a[0],它指向二维数组的0行
注意:在二维数组中,不要把&a[i]简单的理解为元素a[i]的物理地址,因为并不存在a[i]这样一个实际的数据存储单元。
它只是一种地址的计算方法,得到第i行的行地址。
(5). 上面出现的a,a[0],*(a+0),&a[0][0],&a[0]的值都是相同的,不过所包含的含义是有区别的!!!!!!
2.
上面如果没有理解,或者不赞同的话,不要继续看下去!!!指向二维数组a[3][4]的指针
有两种方法将指针指向二维数组。
1.int *p;
2.int (*p)[4];
这两种方法的定义,初始化,使用都是有区别的。
int *p;
这是一个指向一个整型数据的指针,所以我们在初始化的时候,只能把某个整型元素的地址给p。
例如:
// p=a; // p=&a[0]; // p=a[0]; // p=*a; // p=&a[0][0];
//前两个会报错后面三个则不会。
因为二维数组中的元素也是连续存放的,所以也可以把二维数组a[3][4]看成a[12]这个一维数组,然后就可以像一维数组那样使用p了。
int (*p)[4];
这个时候p不是指向整型数据的指针了,而是变成了指向一个包含m个元素的一维数组的指针了。
这个时候p的类型不是int 了,而是int [4]。
// p=a; // p=&a[0]; // p=a[0]; // p=*a; // p=&a[0][0];
// 后三个会报错,前两个不会
int (*p)[4]的使用:
1.这个时候p的类型是int *[4],则p++实际上地址是加了16。
2.可以直接通过(*p)[i]去访问p所指向的一维数组的第i个元素
3.也可以通过二级指针的形式去访问其中的元素。
例如:(*p)[i]和 * (*(p)+i)是等价的。
#include<stdio.h> int main() { int a[2][2]={1,2,3,4}; int (*p)[2]; p=a; printf("%d\n",(*p)[1]); printf("%d\n", *(*(p)+1) ); printf("%d\n", *(*(p)+3) ); printf("%d\n", *(*(p+1)+1) ); return 0; }//输出结果是2,2,4,4
附加:
#include<stdio.h> int main() { int a[4]={1,2,3,4}; int (*p)[4]; //int (*p)[4]也可以指向一维数组 p=&a; //注意这儿不能写成p=a; //这个时候a是一维数组,数组名就代表首元素地址,和p的类型不符合 //a前面加&就可以表示行地址了 //这个时候就有点把一维数组扩展成二维数组那样(有行地址有元素地址)的感觉了 printf("%d\n",(*p)[1]); printf("%d\n", *(*(p)+1) ); printf("%d\n", *(*(p)+3) ); return 0; }
相关文章推荐
- leetcode 10. Regular Expression Matching
- ASP.Net Core MVC6 RC2 启动过程分析[偏源码分析]
- ip更换
- redis命中率计算
- mybatis mapper接口要不要抛出异常
- XmlPullParser
- MATLAB句柄图形对象的创建函数与函数描述
- 剑指Offer——判断平衡二叉树
- 在windows编译MariaDB
- Shell中调用、引用、包含另一个脚本文件的三种方法
- sdut 3253 Game! 博弈
- windows server 2008 R2服务搭建
- MXE (M cross environment) Requirements
- 《Spring技术内幕》学习笔记1——IoC容器体系结构
- SQL_Server_2005_函数大全
- Linux 目录结构
- tp框架总结(二)
- 转:Maven常用命令
- jQuery EasyUI datagrid 无记录时,增加"暂无数据"提示
- [Android] 提高ORMLite插入大量数据效率的解决方案