数组与数组的地址

问题:

int ia[2] = {1, 2};
cout << &ia <<endl;
cout << &ia[0] <<endl;

运行结果如下
0012ff38
0012ff38
我想问一下,如果说ia是的值是数组第一个元素的地址,即&ia[0],那么ia作为一个变量也应该有一个地址,这个地址的值为什么也是和&ia[0]一样呢?如果说
*(&ia)=*(&ia[0])=a[0]=1;(因为&ia的值和&ia[0]的值相等)
但是*(&ia)=ia=&ia[0]=0012ff38才对啊?
0012ff38处存储的是整数值1(*(&ia[0])=ia[0]=1),
还是地址值0012ff38(*(&ia)=ia=0012ff38呢?
大家讨论一下,我 也没有弄明白? 

======================================================================================

回答:

数组是一个类型,这是勿容置疑的。如 int ia[2] = {1, 2}; 中,ia的类型是int[2]。
因此,ia是一个变量,这也是勿容置疑的,它是类型为int[2]的变量。
既然是变量,就需要分配内存空间,就有地址,这也是肯定的。本例中,数组变量ia的地址就是0012ff38。它即是int[2]变量ia的地址,也是int变量ia[0]的地址,所以&ia = &ia[0]这点是很容易理解的,因为数组的内存就是这么分配的。
问题在于为什么(ia==0012ff38)。这里就要考虑数组类型的特殊性了。是的,ia是一个数组变量,但是ia可以隐式转换成一个指针常量(注意是 T* const,不是const T*,即这个指针本身保存的地址不会变化,永远是&ia,但是这个地址上的值,即ia[0]是可变的)。
具体地说,如果int[2]是一个类class int_2,那么编译器是这么写int_2的:
class int_2
{
....
public:
    operator (int* const)() { return (int* const)this; }
....
}

所以,在对ia直接访问时,你看到值其实是其this指针地值,即ia == &ia,它的实质是
     int* const pia = &ia;
     pia == &ia
     当然就是正确的了。
提供这个隐式转换是为了方便数组的访问。比如ia[1],它等价于*(ia+1),也就等价于
     int* const pai = &ia;
     *(pia+1)
     当然就可以访问数组下标为1的元素了。
(注意 a[n] 与 *(a + n) 永远是等价的。比如你会发现 ia[1] == 1[ia].因为在几乎所有的编译器中,a[n]都是先翻译成*(a+n)再进一步编译的)
     隐式转换是在所有需要时有编译器自动完成的。比如做 *(ia)时,由于int_2没有提供*操作符,而所有指针都提供了操作符,所以将ia转换成(int* const)&ia了,同样的,*(ia+1)的例子因为要完成+操作而做了转换,ia[1]则是定义了
int& int_2::operator[](size_t idx) { return *(ia+idx);} 在这个函数体内部做了隐式转换。

因此,当发现 ia == &ia 时没必要感到奇怪,这只是为了完成==操作而做了一次隐式转换罢了。
对于楼主提出的问题,结论如下:
1、&ia == &ia[0] == 0012ff38 成立,因为ia,ia[0]的地址都是0012ff38
2、0012ff38处存储的是整数值1 成立,因为ia[0] = *(ia) = 1 //此处*(ia)做了隐式转换
3、*(&ia) == ia == &ia[0] == 0012ff38 成立,
    其中*(&ia) == ia 是同一律,ia == &ia[0] 左式做了一次隐式转换
4、*(&ia) == *(&ia[0]) == a[0] == 1 不成立!!
     其假设成立的依据是&ia == &ia[0]。但是它们虽然是一个地址,但不是同一个类型的指针!不同类型的指针在进行==评估时,可以转成size_t做比较,但当它们分别进行&操作时,其类型差别就显示出来了。&ia的类型时(int[2])* ,或按上面说的,写成int_2* 。而&ia[0]的类型则是int*。如此*(&ia)的类型是int_2;而*(&ia[0])类型int 。int2本身没有定义==操作,只能通过隐式转换成int* const,此时它的值就和*(&ia[0])完全不一样了。
    所以*(&ia) == 0012ff38 正确,*(&ia) == 1 错误。这并不矛盾,只要你知道编译器定义了一个数组到指针常量的隐式转换就行了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值