C 指针';s地址和从指针转换的int值

C 指针';s地址和从指针转换的int值,c,C,我认为ptr的地址和a的地址是一样的。我还认为ptr的地址和指针转换的int值是一样的 但安慰的结果否定了我,原因是什么?我怎么能理解结果呢 #包括 int main(){ inta[5]={1,2,3,4,5}; int*ptr=(int*)((int)a); printf(“a的地址:%p\n”,a); printf(“ptr的地址:%p\n”,ptr); printf(“ptr的int值:%x”,(int)ptr); 返回0; } 控制台的结果是 a's address: 0x7ffee

我认为ptr的地址和a的地址是一样的。我还认为ptr的地址和指针转换的int值是一样的

但安慰的结果否定了我,原因是什么?我怎么能理解结果呢

#包括
int main(){
inta[5]={1,2,3,4,5};
int*ptr=(int*)((int)a);
printf(“a的地址:%p\n”,a);
printf(“ptr的地址:%p\n”,ptr);
printf(“ptr的int值:%x”,(int)ptr);
返回0;
}
控制台的结果是

a's address: 0x7ffee8d30600 
ptr's address: 0xffffffffe8d30600 
ptr's int value: e8d30600
ps


我已经编辑了标题,最初模棱两可的标题是“指针的地址和指针的int值之间有什么区别”

我已经理解了。机器基于64位地址。将地址转换为int值将丢失地址的上限值。所以这里a的地址不同于ptr的地址


如果在C++中使用指针,我们可以使用<代码> ItpTrpT><代码>或最好是<代码> uTunpTrtt><代码>

不是你真正想要达到的目的。int仅包含32位值。因此,(int)ptr将只返回ptr地址的32位值,这是您得到的较低的4个字节。

C有一个用于存储指针值的:

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\u t
值是从仍然有效的指针获得的,则从
uintptpr\u t
到指针类型的转换仅提供可用指针。这可能很微妙。即使在表示形式相同的处理器体系结构上(几乎所有的处理器体系结构都是如此),编译器也可以假定您不会做太疯狂的事情,并相应地进行优化。有关一些示例,请参见

在本例中,您没有尝试将指针值存储在
uintpttr\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
    ,将其扩展到所需的宽度,并将其移动到无符号范围,得到264-388823552=0xFFFFFFFF8D30600
  • (int)p
    应用与上述
    (int)a
    相同的截断过程,并再次生成
    -388823552
    。但是您正在使用
    %x
    说明符将其打印出来,因此此值将转换为
    无符号的
    (平台上的32位类型),这将给出值232-388823552=0xe8d30600

指针有三个方面。与C中的任何变量一样,它也有一个地址(例如:表达式
&ptr
)。指针还包含一个地址(例如:表达式
ptr
)。最后,您可以得到它所指向的内容(例如:表达式
*ptr
)。每一个都有一个特定的类型,
int**
int*
int
。也就是说,谁告诉过你“ptr的地址与其int值相同”是天真的。和
int*ptr=(int*)((int)a)
完全是胡说八道。尤其是在x86-64平台上,指针的大小为64位并将其强制转换为int将删除信息。您不是在打印指针的地址,而是在打印指针的值。@WhozCraig谢谢您的回答。我编辑了标题和一些内容,这可能会导致歧义。指针只是一个普通变量,它的值包含其他对象的地址。换句话说,指针指向可以找到其他内容的地址。例如,
inta=5
将立即值
5
存储为其值
int*b
创建指向
int
b=&a
存储
a
的地址(当前存储
5
的内存地址)作为其值。如果需要存储在指针持有的内存地址处的值,可以使用一元
'*'
运算符取消对指针的引用,例如
int c=*b将初始化
c=5
)。