您的位置:首页 > 其它

BLOG1:关于指针数组地址偏移量的一点小见解

2018-01-06 17:04 239 查看
  我是一名在校大一学生,在C语言的学习中难免会遇到一些这样那样的问题。我喜欢解决问题,喜欢思考。
  这是我在CSDN上的第一篇博客,来源于高中同学的问题,希望能得到大牛们的看法,也算是向各位大牛问好。
  废话不多说,问题如下:
#include <stdio.h>
int main()
{
    char p[3][4]={"ABC","DEF","GHI"};
    char *q[3],**pp;
    pp=q+2;
    q[0]=p[1];
    q[1]=p[2];
    q[2]=p[0];
    putchar(pp[-1][-2]+3);
    return 0;
}
为什么输出结果是I呢?
显然这是一个多重的指针数组问题,于是凭借我所学的知识我走到了putchar这里,但是pp[-1][-2]又让我头大。
下面我试着用地址的偏移量来解释,发现可以解释得通,而且printf了几次,按照地址偏移量来讲完全讲得通。为了给同学讲明白,于是我陷入了思考。
(1)处理这个问题要从全局考虑,这是一个多重指针、多维数组、地址偏移量的综合问题。
(2)问题落脚在putchar这里,3是ASCII码的增减可以先不管,pp[-1][-2]是什么?其实就是*(*(pp-1)-2)。
(3)pp和q怎么处理?都代入*(*(pp-1)-2)中。
(4)代入后怎么处理?看问题要看透,地址的偏移量是什么,是二维数组地址的偏移量,pp和q都是虚的,本质上说p是基础。
(5)下面进行简化,我用不规范的写法表示:*(*(pp-1)-2)==*(*(q+1)-2)==*(q[1]-2)==*(p[2]-2)
(6)由于多维数组在计算机内是连续存储的,所以*(p[2])=='G',*(p[2]-1)=='\0',*(p[2]-2)=='F',所以结果自然是'F'+3就是'I'了,输出结果I
这个问题有什么更简洁的思路吗?当然有。
我们知道pp和q都是虚的,从本质入手,pp[-1][-2]怎么处理?
我们建立一个观念:
(1)多维数组
对于多维数组(以三维为例)a[4][4][4]。'[]'只是一个逻辑上的级别表示(由于*(*(*(a+i)+j)+k)和a[i][j][k]是等价的,两者都是逻辑上的表示形式),也就是说它的'[]'是可以左右结合的。a是地址,a[i]是地址,a[i][j]同样是地址,而且a的值等于a[0]的值等于a[0][0]的值,解地址或者说级别的表示只是逻辑上的关系,这三个地址都对应同一个元素,只不过逻辑上的解地址的次数不一样,所以逻辑级别不同但是值相等。
(2)多重指针
多重指针与多维数组不同,是重新定义了一个变量来存储地址,所以*和**和***是不一样的。多重指针的逻辑级别不同值也不同。
易知,多重指针和多位数组的逻辑关系相同但值不同。

所以我们看得再透一点这个问题其实就是逻辑关系的考察,二级地址pp、p、q,一级地址p[i]、q[i],元素p[i][j]。
形象的说,pp[-1][-2]就是(pp[-1])[-2]就是q[1][-2]就是p[2][-2],然后根据地址偏移量就可以得出了。

总结一下,
从指针和数组的角度:
多重指针反映的是数据的逻辑关系。
多维数组反映了数据的逻辑关系和数据关系:
逻辑关系体现在当访问数据信息时,需要一层一层地解地址;
数据关系体现在一个数据唯一对应一个地址,所以p=p[0]=&p[0][0]#include <stdio.h>
#include <stdlib.h>

int main()
{
int p[3][3]={{1,2,3},{4,5,6},{7,8,9}};
printf("p[0][0]=%d\n",p[0][0]);
printf("p=%p ",p);
printf("p[0]=%p ",p[0]);
printf("&p[0][0]=%p",&p[0][0]);
return 0;
}结果如下

从方法论的角度:

解决问题,关键在于认识,对问题的认识、对知识的认识。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: