我认为ptr的地址和a的地址彼此相同。而且我还认为ptr的地址与从指针转换的int值相同。
但是控制台的结果拒绝了我。原因是什么?我如何理解结果。
#include <stdio.h>
int main() {
int a[5] = {1, 2, 3, 4, 5};
int *ptr = (int *) ((int) a);
printf("a's address: %p \n", a);
printf("ptr's address: %p \n", ptr);
printf("ptr's int value: %x", (int)ptr);
return 0;
}
控制台的结果是
a's address: 0x7ffee8d30600
ptr's address: 0xffffffffe8d30600
ptr's int value: e8d30600
ps
我已经编辑了标题,原始的模棱两可的标题是“指针的地址和指针的int值之间有什么区别”
答案 0 :(得分:1)
并不是您要在这里实现的目标。一个int仅包含32位值。因此,(int)ptr将仅返回ptr地址的32位值,即您获得的低4个字节。
答案 1 :(得分:1)
C有一个type uintptr_t
,可用于存储指针值:
void *p = …;
uintptr_t u = (uintptr_t)p;
void *q = (void *)q;
// here q is equivalent to p
在许多平台上,u
像p
一样存储p
指向的对象的地址,而u
和p
具有内存中的表示相同。这不是义务:允许C实现使用不同的表示形式。但是,使用相同的表示形式是满足C标准要求的最明显方法。
请注意,如果uintptr_t
值是从仍然有效的指针获得的,则从uintptr_t
到指针类型的转换仅提供可用的指针。这可能是微妙的。即使在表示形式相同的处理器体系结构上(几乎都是它们),编译器也可以假定您并没有做太多疯狂的事情,并相应地进行了优化。有关示例,请参见responses to the Cerberus survey。
在您的情况下,您没有尝试将指针值存储在uintptr_t
中,而是尝试将其存储在int
中。这失败了,因为在您的平台上,int
太小,无法存储指针值。显然,在您的平台上,指针是64位值,而int
是32位值。这是很常见的安排。
a
是数组的地址。 (这是指向数组第一个元素的指针,并且在您的平台上,指针仅由地址表示。)。在此特定运行中,它是0x7ffee8d30600。那里没什么了不起的。(int) a
将a
的地址转换为int
的值。这是实现定义的。您的实现会执行通常的操作:由于int
太小,它会截断该值。将上述地址截断为无符号的32位值将产生0xe8d30600
。为了获得带符号的值,最高有效位变为符号位,因此a
恰好为负:a
为-388823552
。p
是(int *) ((int) a)
。再次由实现定义此转换,并且您的实现又执行与大多数操作相同的操作。它采用32位带符号的int
值-388823552
,将其扩展到所需的宽度并将其移至无符号范围,得到2 64 -388823552 = 0xffffffffe8d30600。(int)p
应用与上面的(int)a
相同的截断过程,并再次产生-388823552
。但是您正在使用%x
说明符将其打印出来,因此该值将转换为unsigned
(平台上的32位类型),其值为2 32 -388823552 = 0xe8d30600。答案 2 :(得分:0)
我明白了。机器基于64位地址。将地址转换为int值将丢失地址的高位值。因此,这里a的地址与ptr的地址不同。
如果要在C ++中使用指针,我们可以使用intptr_t
或最好使用uintptr_t