#include
int main(int argc, char *argv[])
{
int a[5] = {1, 3, 5, 7, 9};
printf("%p,%p,%p\n", a, &a, &a[0]);
int *p1 = a;
int *p2 = (int*)&a;
int (*p3)[5] = &a;
printf("%d,%d,%d \n", *(p1+1), *(p2+1), *(*p3+1));
int *p4 = (int*)(&a+2);
int *p5 = (int*)((int)a+4);
printf("%d,%d", p4[-6], *p5);
return 0;
}
-----------------------------
语句2中,a和&a都是得到数组a的首元素的内存地址。把a
当作指向数组对象的首地址的指针,即为数组a的首元素的内存地址;而&a则是对数组对象取地址。
----------------------------------------------------------------------
a和&a都不是数组a首元素的地址!数组a首元素的地址是&a[0],a与&a所代表的地址值只不过跟&a[0]相同,
但意义和类型都是不同的,a是数组a的标识符,代表数组a,其类型是int[5],而&a是数组a的首地址,类型是int(*)
[5],&a[0]的类型是int*,只不过因为地位特殊,地址值才与a、&a相同。
语句3中,用数组a去初始化指针p1,将数组a隐式转换为指针;
-------------------------------------------------
并非将a赋予p1的过程中a隐式转换为指针,而是a放在表达式中的时候已经隐式转换为指针了,a还没有赋予p1的时候,隐式转换已经完成了,a的类型从
int[5]转换为int*
语句4中,&a的类型为int (*)
[5],即指向数组a[5]的指针,而在该句中,(int*)&a则将&a显式转换为int *
类型的指针,于是将p2初始化为指向数组的首元素的指针。
语句5中,p3为指向整形数组的指针,并用&a初始化,故*p3为p3指向的整形数组。
语句6中,*(p1+1),*(p2+1), *(*p3+1)的值都为3。
语句7中,&a+2将指向下两个元素。因为&a为指向数组a[5]的指针,故其实际移动的内存为两倍a[5]的内存(一个元素为20字
节,即40个字节),由a[5]的首元素地址向前移动40个字节,并将该地址赋值给p4(经过显式转换)。
语句8中,首先(int)a,将a显式转换成整形的值,加上4,实际上加了一个整形的地址长度,并将该地址赋值给p5(经过显式转换),实际上相当于移动
到数组的下一个元素。
语句9中,,p4[-6]即为*(p4-6),将p4向后移动了6个sizeof(int*)
的地址长度(24),于是移动到了数组中第5个元素的地址,所以,p4[-6]为9; *p5则为3.
------------------------------------------------------------------------
注意[-6]是符合标准的,标准规定下标运算的时候,步长的类型是int,因此可以是负数。
阅读(694) | 评论(0) | 转发(0) |