#include<stdio.h>
int main(void){
int a[3] = {1,2,3};
int *p;
p = &a+2;
// here p and &a+2 will going to be same...having some particular address on memory
*p = 56;
// m writing 56 on *(p) or *(&a+2)...
printf("%d %d\n",*p,*(&a+2));
return 0;
}
o / p显示我是什么!! *p = 56
但*(&a+2)
=与&a+2
相同......
对于p = &a+1
,它给了我一堆粉碎......
在*(*(&a+2))
给我想要的结果56
...
任何人都可以向我解释这背后的确切原因是什么?
p = &a+2;
在功能上等同于
p = &(a[6]);
因为在&a
上加两个sizeof(a)*2
加&a
,而sizeof(a)*2
等于sizeof(a[0])*3*2
。取消引用生成的指针会引发未定义的行为,因为它超出了数组的末尾。
#include <stdio.h>
int main(void) {
int a[3] = {1,2,3};
int *p = &a+2;
printf("a @ %p\n", (void*)a);
printf("a @ %p\n", (void*)&a);
printf("a[0] @ %p\n", (void*)&(a[0]));
printf("a[2] @ %p\n", (void*)&(a[2]));
printf("p = %p\n", (void*)p);
printf("a[6] @ %p\n", (void*)&(a[6]));
return 0;
}
给
$ gcc -Wall -Wextra -pedantic --std=c99 a.c -o a && a
a.c: In function ‘main’:
a.c:5:14: warning: initialization from incompatible pointer type [enabled by default]
int *p = &a+2;
^
a @ 0x3878b9c3030
a @ 0x3878b9c3030
a[0] @ 0x3878b9c3030
a[2] @ 0x3878b9c3038
p = 0x3878b9c3048
a[6] @ 0x3878b9c3048
你的意思是p=a+2;
,而不是p=&a+2;
。后者形成一个指向数组a
(使用&a
)的指针,然后尝试形成一个指向不存在的其他数组的指针(如果它存在,它将是多维数组中的一行)。很少使用指向数组的指针,这有助于人们混淆数组和指向它们decay的指针。
任何人都可以向我解释这背后的确切原因是什么?
原因是您正在调用未定义的行为,因此您的编译器以及您的程序可以执行它想要的任何操作。这几乎就是“未定义行为”的定义:标准没有说明正确的事情是什么,所以程序可以做任何事情。
仅仅因为*(*(&a+2))
给出了正确的答案并不意味着&a+2
是有效的代码。在很多情况下,未定义的行为可能导致工作程序,但不能保证这样的程序将继续工作,甚至在您进行进一步更改时继续编译。
正如几个人已经指出的那样,未定义的行为来自p = &a+2
,它将未初始化的地址分配给不兼容的指针。