测试平台:64位 X86 Ubuntu
1. 代码:
#include <stdio.h>
void main(void)
{
char (*p)[5] = NULL;
char (*p1)[5] = NULL;
char a[5] = {0,1,2,3,4};
p = a;
p1 = &a;
printf("a[5] = %d\n", a[5]);
printf("p = %p, p+1 = %p, p1 = %p, P1+1 = %p\n", p, p+1, p1, p1+1);
printf("*(char *)p = %d, *((char *)p+1) = %d, *(char *)p1 = %d, *((char *)p1+1) = %d\n", *(char *)p, *((char *)p+1), *(char *)p1, *((char *)p1+1));
printf("*(char *)p = %d, *(char *)(p+1) = %d, *(char *)p1 = %d, *(char *)(p1+1) = %d\n", *(char *)p, *(char *)(p+1), *(char *)p1, *(char *)(p1+1));
printf("*p = %p, *(p+1) = %p, *p1 = %p, *(P1+1) = %p\n", *p, *(p+1), *p1, *(p1+1));
printf("**p = %d, **(p+1) = %d, **p1 = %d, **(P1+1) = %d\n", **p, **(p+1), **p1, **(p1+1));
}
2. 编译:
baoli@ubuntu:~/c$ gcc test.c
test.c: In function ‘main’:
test.c:9:7: warning: assignment from incompatible pointer type [enabled by default]
p = a;
^
3. 结果:
baoli@ubuntu:~/c$ ./a.out
a[5] = 127
p = 0x7fff48848650, p+1 = 0x7fff48848655, p1 = 0x7fff48848650, P1+1 = 0x7fff48848655
*(char *)p = 0, *((char *)p+1) = 1, *(char *)p1 = 0, *((char *)p1+1) = 1
*(char *)p = 0, *(char *)(p+1) = 127, *(char *)p1 = 0, *(char *)(p1+1) = 127
*p = 0x7fff48848650, *(p+1) = 0x7fff48848655, *p1 = 0x7fff48848650, *(P1+1) = 0x7fff48848655
**p = 0, **(p+1) = 127, **p1 = 0, **(P1+1) = 127
4. 分析:
1)p和p1是一个指针,他们指向一个数组,代表整个数组的地址。
2)由于a代表数组首元素的地址,所以赋值给p时出现了警告,编译器将其进行类型转换后赋值给p,赋值后的p还是代表数组的地址
3)赋值后的p和p1都代表数组的地址,而不是首元素的地址。所以p+1=P1+1,且都是偏移5个字节
4)*(char *)(p+1) = *(char *)(p1+1) = 127,这里的127应该是a[5]
5)注意:*((char *)p+1) = 1,*(char *)(p+1) = 127
6)由于p是一个指向数组的指针,*p = p, p+1=*(p+1),why?
类似于两级指针(把数组也当成一级指针,尽管数组不是指针),p代表一个数组的地址,*(p+0)代表一个数组首元素的地址,所以p=*p,但是他们表示的范围不同,**p即代表a[0];p+1与*(p+1)同理。
7)int *p; p = a才正确,因为a代表数组首元素地址,是一个char元素的地址,即char *。