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);