4.3.2,a 和&a 的区别

 

 

4.3.2,a 和&a 的区别
通过上面的分析,相信你已经明白数组和指针的访问方式了,下面再看这个例子:
main()
{
 int a[5]={1,2,3,4,5};
 int *ptr=(int *)(&a+1);
 printf("%d,%d",*(a+1),*(ptr-1));
}

打印出来的值为多少呢? 这里主要是考查关于指针加减操作的理解。
对指针进行加1 操作,得到的是下一个元素的地址,而不是原有地址值直接加1。所以,
一个类型为T 的指针的移动,以sizeof(T) 为移动单位。因此,对上题来说,a 是一个一
维数组,数组中有5 个元素; ptr 是一个int 型的指针。
&a + 1: 取数组a 的首地址,该地址的值加上sizeof(a) 的值,即&a + 5*sizeof(int),也
就是下一个数组的首地址,显然当前指针已经越过了数组的界限。
(int *)(&a+1): 则是把上一步计算出来的地址,强制转换为int * 类型,赋值给ptr。
*(a+1): a,&a 的值是一样的,但意思不一样,a 是数组首元素的首地址,也就是a[0]的
首地址,&a 是数组的首地址,a+1 是数组下一元素的首地址,即a[1]的首地址,&a+1 是下一
个数组的首地址。所以输出2
*(ptr-1): 因为ptr 是指向a[5],并且ptr 是int * 类型,所以*(ptr-1) 是指向a[4] ,
输出5。
这些分析我相信大家都能理解,但是在授课时,学生向我提出了如下问题:
在Visual C++6.0 的Watch 窗口中&a+1 的值怎么会是(x0012ff6d(0x0012ff6c+1)呢?
/*
剖析
A       是数组首元素的首地址,  a+1 是下一个元素
&a[0]   是数组首元素的首地址,                  
&a      数组的首地址            a+1 是下一个数组
*/
C 语言引入一个术语-----“可修改的左值”。  A[10];
意思就是,出现在赋值符左边的符号所代表的地址上的内容一定是可以被修改的。换句话说,就是我们只能给非只读变量赋值。既然已经明白左值和右值的区别,下面就讨论一下数组作为左值和右值的情况:
当a 作为右值的时候代表的是什么意思呢?
很多书认为是数组的首地址,其实这是非常错误的。
a 作为右值时其意义与&a[0]是一样,代表的是数组首元素的首地址,而不是数组的首地址。这是两码事。

但是注意,这仅仅是代表,并没有一个地方(这只是简单的这么认为,其具体实现细节不作过多讨论)来存储这个地址,也就是说编译器并没有为数组a分配一块内存来存其地址,这一点就与指针有很大的差别。
a 作为右值,我们清楚了其含义,那作为左值呢?a 不能作为左值!
这个错误几乎每一个学生都犯过。编译器会认为数组名作为左值代表的意思是a 的首元素的首地址,但是这个地址开始的一块内存是一个总体,我们只能访问数组的某个元素而无法把数组当一个总体进行访问。所以我们可以把a[i]当左值,而无法把a当左值。其实我们完全可以把a 当一个普通的变量来看,只不过这个变量内部分为很多小块,我们只能通过分别访问这些小块来达到访问整个变量a 的目的。


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值