C 为什么强制转换后指针的值会发生变化?

C 为什么强制转换后指针的值会发生变化?,c,assembly,C,Assembly,代码: 输出: int main(void) { register int rsp asm("rsp"); int temp=rsp; printf("\n (rsp)%p \n", rsp); printf("\n (temp)%p \n", temp); printf("\n (void*)(rsp)%p \n", (void*)rsp ); printf("\n (void*)(temp)%p \n", (void*)temp ); return 0; } 我怀疑这是一个愚蠢的问题,

代码:

输出:

int main(void) {
register int rsp asm("rsp");
int temp=rsp;

printf("\n (rsp)%p \n", rsp);
printf("\n (temp)%p \n", temp);
printf("\n (void*)(rsp)%p \n", (void*)rsp );
printf("\n (void*)(temp)%p \n", (void*)temp );

return 0;
}
我怀疑这是一个愚蠢的问题,但为什么在强制转换后指针的值会发生变化呢?我尝试了不同的类型,我总是得到相同的偏移量。 多谢各位

但为什么在强制转换之后指针的值会发生变化呢

int
rsp
int
,而不是指针

使用
“%p”
int
的未定义行为

 (rsp)0xffffcbe0

 (temp)0xffffcbe0

 (void*)(rsp)0xffffffffffffcbe0

 (void*)(temp)0xffffffffffffcbe0
然而,让我们假设转换为无符号的值是由OP打印的

printf("\n (rsp)%p \n", rsp);   // UB
printf("\n (temp)%p \n", temp); // UB
当代码转换指向
int
的指针时,如
寄存器intrsp asm(“rsp”),它可能会失去意义。将
int
转换为指针时,会出现各种转换机制,如符号扩展,以处理狭窄的
int
“%p”
具有特定于实现的格式

需要说明的是:OP的代码并不一定打印原始的
asm(“rsp”)
。(特定于编译器的扩展名)

C提供可选的整数类型
(u)intptr\u t
,提供从等效整数和对象指针到等效整数和对象指针的转换。要将对象指针保存为整数,请使用这些类型。不幸的是,C缺少用于打印非
void*
指针和
(u)intptr\u t
的值的锁存打印说明符,因此强制转换为以下内容

printf("\n (rsp)0x%x \n", (unsigned) rsp);   // (rsp)0xffffcbe0
printf("\n (temp)0x%x \n", (unsigned) temp); // (temp)0xffffcbe0
#包括
#包括
char*s=“rsp”;
printf(“指针%p\n”,(void*)s);
uintptr_t i_ptr=(uintptr_t)s;
printf(“整数0x%jX\n”,(uintmax_t)i_ptr);

32位int和64位指针,也许我很确定前两个
printf
会导致UB@Peter-您确定最后两个
printf
是UB吗?编译时,始终启用所有警告,然后修复这些警告。您使用RSP的事实告诉我们您使用的是64位。但是,您将(c变量)RSP声明为int(通常为32位)。所以前两个printf是RSP的截断表示。第二个2是前两个的符号扩展版本(想想:(int)-1和(long-long)-1)。据猜测,这些都不代表RSP的实际值。尝试将c变量RSP声明为64位类型(uint64\t)。
#include <stdint.h>
#include <stdio.h>

char *s = "rsp";
printf("pointer %p\n", (void *) s);

uintptr_t i_ptr = (uintptr_t) s;
printf("integer 0x%jX\n", (uintmax_t) i_ptr);