指针的地址和从指针转换的int值有什么区别

时间:2019-06-02 03:05:22

标签: c

我认为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值之间有什么区别”

3 个答案:

答案 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

在许多平台上,up一样存储p指向的对象的地址,而up具有内存中的表示相同。这不是义务:允许C实现使用不同的表示形式。但是,使用相同的表示形式是满足C标准要求的最明显方法。

请注意,如果uintptr_t值是从仍然有效的指针获得的,则从uintptr_t到指针类型的转换仅提供可用的指针。这可能是微妙的。即使在表示形式相同的处理器体系结构上(几乎都是它们),编译器也可以假定您并没有做太多疯狂的事情,并相应地进行了优化。有关示例,请参见responses to the Cerberus survey

在您的情况下,您没有尝试将指针值存储在uintptr_t中,而是尝试将其存储在int中。这失败了,因为在您的平台上,int太小,无法存储指针值。显然,在您的平台上,指针是64位值,而int是32位值。这是很常见的安排。

  • a是数组的地址。 (这是指向数组第一个元素的指针,并且在您的平台上,指针仅由地址表示。)。在此特定运行中,它是0x7ffee8d30600。那里没什么了不起的。
  • (int) aa的地址转换为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