例子:
#include <stdio.h>
int main()
{
char a[5] = {'a', 'b', 'c'};
// 以下3行效果相同
char *p = a;
// char *p = a + 0;
// char *p = &a[0];
char **pp = &p;
printf("a: %p, *a: %p, &a: %p, sizeof(a): %d\n", a, *a, &a, sizeof(a));
printf("a+0: %p, *(a+0): %p, sizeof(a+0): %d\n", a+0, *(a+0), sizeof(a+0));
printf("a[0]: %p, &a[0]: %p, sizeof(a[0]): %d\n", a[0], &a[0], sizeof(a[0]));
printf("\np: %p, *p: %p\n", p, *p);
printf("&p: %p, &*p: %p\n", &p, &*p);
printf("\npp: %p, *pp: %p, **pp: %p\n", pp, *pp, **pp);
printf("&pp: %p, &*pp: %p, &**pp: %p\n", &pp, &*pp, &**pp);
// char (*ap)[5] = a; 非法语句
// 数组指针只能指向数组,a表示数组首元素的地址而不是数组的地址,尽管二者具有相同的值
char (*ap)[5] = &a;
printf("\nap: %p, *ap: %p\n", ap, *ap);
printf("&ap: %p, &*ap: %p\n", &ap, &*ap);
return 0;
}
结果(具体数值可能因运行环境不同而不同):
a: 0061FF2B, *a: 00000061, &a: 0061FF2B, sizeof(a): 5
a+0: 0061FF2B, *(a+0): 00000061, sizeof(a+0): 4
a[0]: 00000061, &a[0]: 0061FF2B, sizeof(a[0]): 1
p: 0061FF2B, *p: 00000061
&p: 0061FF24, &*p: 0061FF2B
pp: 0061FF24, *pp: 0061FF2B, **pp: 00000061
&pp: 0061FF20, &*pp: 0061FF24, &**pp: 0061FF2B
ap: 0061FF2B, *ap: 0061FF2B
&ap: 0061FF1C, &*ap: 0061FF2B
C语言中,数组名(假设为a)在某些情况下可以当作指针使用。不包括的情况:
- sizeof(a):表示数组的实际长度。
- 运算:非法,此时name相当于指针常量,不可修改。
- &a:表示数组的地址,而a相当于&a[0],表示数组首元素的地址。
分析:
- 数组a
- 占据5个连续的内存空间,0061FF2B到0061FF2F。
- 指针p
- p指向a的第一个元素,所以是红色的0061FF2B,而不是蓝色的0061FF2B。
- *p表示p指向的地址的值,即a[0]的值,00000061。
- &p表示p自身的地址,0061FF24。
- &*p表示*p的地址,即a[0]的值的地址,0061FF2B。
- 指针的指针pp
- pp指向p,表示p的地址,0061FF24。
- *pp表示pp指向的地址的值,即p的值,0061FF2B。
- **pp表示进一步寻值,即*p,00000061。
- &pp表示pp自身的地址,0061FF20。
- &*pp表示*pp的地址,即p的地址,0061FF24。
- &**pp表示**pp的地址,即&*p,0061FF2B。
- 数组指针ap
- ap指向作为整体的a,所以是蓝色的0061FF2B。
- *ap表示ap指向的地址的值,即作为整体的a的值,0061FF2B。
- &ap表示ap自身的地址,0061FF1C。
- &*ap表示*ap的地址,即作为整体的a的值的地址,0061FF2B。
结语:
- 指针也有自己的地址。
- 指针的指针指向的是指针,而不是指针的指向。
个人观点:&*连续出现的时候可以相互抵消。