当前位置: 首页 > >

数组名和指针的区别和联系、数组名取地址&a

发布时间:

前言
在很多用到数组名字的地方,编译器都会自动地将其替换为一个指向该数组首元素的指针。所以,在大多数表达式中,使用数组名其实是在使用一个指向该数组首元素的指针。
数组名其实是种特殊的指针

int main()
{
int a[] = { 0,1,2,3,4 };
printf("a is %x
", a);
printf("&a is %x
", &a);
printf("&a[0] is %x
", &a[0]);

int *p = &a[0];
//int * p1 = &a;
//上句报错信息:&a的类型为int(*)[5],不能用来初始化int *
decltype(a) t;
decltype(&a) tt;

cout << "p is "<

printf("a + 1,p + 1 are %x,%x
", a + 1,p + 1);
printf("&a + 1 is %x
", &a +1);

cout << sizeof(a) << " " << sizeof(&a) << endl;
}



    从局部变量表可以看出,数组a和指针p的构成是很相似的。它们实际存的都是一个地址,都会指向一个对象(或多个对象的第一个对象)。所以说数组名其实是种特殊的指针。但它俩自身又有不同,指针本身是一个对象,在内存中是为其分配了空间的;但数组名在内存空间中没有分配到空间(这将导致&a操作的效果可能和预想的不大一样)。

数组名a、数组名取地址&a、数组首元素地址&a[0]、指向数组首元素的指针*p


    a既然是种特殊的指针,那么其打印时就会是存的地址。&a的类型是int(*)[5](读法从小括号里往外,首先是指针,然后是大小为5的数组,然后数组元素类型是int),从局部变量中看到其类型也可写成int[5] *:即指向大小为5的int数组的指针。由于数组名没有内存分配空间,所以&a取地址还是取到的是数组首元素的地址。&a[0]就是取一个int对象的地址,这个int对象是数组首元素。综上所述,就造成了a &a &a[0]三者打印出来的地址是一样的。p,指向数组首元素的指针。a + 1,p + 1都是按照元素大小的字节数(4字节),增加4。&a + 1,前面说了 &a的类型是指向大小为5的int数组的指针,大小为5的int数组所占字节数为20,所以&a + 1就应该增加20。sizeof(a)为20,因为数组总的字节大小为20。sizeof(&a)为4,因为&a是一种指针,指针在32位系统中占4字节。

指向数组首元素的指针可使用操作符[]

a[1], p[1]都能取出数组的1索引元素。
上面这句的效果和原理和这句*(a + 1),*(p + 1)一样。


对了,你也可以int *p = a,也是指向数组首元素的指针。


指向非首元素的指针使用操作符[]

int *p = &a[2]指向了2索引的元素。
int j = p[1],3索引的元素。相当于*(p + 1)
int k = p[-2],0索引的元素。这里是内置的取下标操作,所以可以用有符号数。(标准库类型取下标的话,则必须使用无符号数)
但一定注意这里的p都必须指向数组中的元素。



友情链接: