一维指针和二维指针指向二维数组的一些问题

废话少说,先上自己Dev c++上的代码:
   
   
#include<stdio.h>
int main (){
int c[2][3]={15,2,3,4,5,6}, *p, (*rp)[3],*q,i;
p = (int*)c;
rp=c;
q=c;
printf ("**rp=%d\n *rp=%p\n c=%p\n p = %p\n q=%p\n *q=%d\n ",**rp,*rp,c,p,q,*q);
printf("*(rp+1)=%p\n*(p + 1)=%p\n", rp+1,p + 1);
for(i=0;i<6;i++) {
printf("*rp[%d]=%d\n",i,*rp[i]);
}
printf("\n");
for(i=0;i<6;i++) {
printf("q[%d]=%d\n",i,q[i]);
}
return 0;
}
首先定义一个2*3的二维数组,定义一个一维指针p和q,定义一个指向指针的指针(*rp)[3],问题来了!
一.将二维数组地址赋给一维指针的问题:
第一种赋值方法:将二维数组c强制转换成一维的指针类型,并将其赋给一维指针p(代码第4行)
第二种赋值方法:将二维数组c的地址直接赋给一维指针(代码第6行)
第一种赋值方法和第二种赋值方法的区别是: 第一种赋值方法可以通过Dev c++的编译,第二种赋值方法不能通过Dev C++的cpp文件编译(会出现error),在后缀名为c 的文件中会出现warning(警告的中文意思是指针类型不匹配),但可以运行!
两者运行得结果均为

因此两种的赋值方法在本质上区别不大,但通过查阅资料得知,c++对指针的要求很严格,因此建议如果要用一维指针指向二维数组时候,采用第一种直接强制类型转换的方法比较合法规范,这样会避免出现无可预知的错误!


二.一维指针和二维指针的偏移地址问题
在代码的定义类型上,(*rp)[3]表示指向含3个元素的一维整形数组的指针变量,通俗的说法是指向指针的指针,也即是二维指针,为了规范,我用强制类型转换的一维指针p与二维指针rp就偏移地址的问题做一个比较。

代码第八行:printf("*(rp+1)=%p\n*(p + 1)=%p\n", rp+1,p + 1);
运行的结果是:

再与初始定义的地址相比较:


仔细比较后发现,一维指针和二维指针偏移地址为1时候,一维指针地址偏移了4,二维指针地址偏移了12(指针地址都是以16进制表示)
原因:二维指针rp的首地址是c[0],一维指针p的首地址是c[0][0],因此rp+1的地址即是c[0]+1==c[1]的地址(这个地址同时也是c[1][0]的地址,p+1的地址即是c[0][0]+1==c[0][1]的地址
(如果不懂,可以参考一下中山大学2011年软件学院的程序设计理论考试关于指针的一道填空题来理解:
填空题有一问是: * q + 3 - p=?
参考答案是6,下面就用上面的分析来解释答案为什么是6
  
  
#include <stdio.h>
int main() {
int a[3][4]={1,5,8,10,11,3,4,8,7};
int *p = (int*)a;
int (*q)[4] = a;
p += 1;
q += 1;
printf("%d\n", *p);
printf("%d\n", **q);
printf("%d\n", (*q)[2]);
printf("%d\n", *q+3-p);
printf("*q=%p\n", *q);
printf("p=%p\n", p);
return 0;
}

p是一维指针,初始地址为a[0][0],所以p+1的地址为a[0][1],q是二维指针,初始地址为a[0],所以q+1的地址为a[1][0],
程序运行后的结果如下


所以p和q的地址相差3(0x10-0x04=12,12/4=3),再加3即为答案6!
这就是一维数组和二维数组的地址偏移的大致区别。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值