为什么投射后指针的值会发生变化?

时间:2016-09-10 14:49:04

标签: 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;
}

输出:

 (rsp)0xffffcbe0

 (temp)0xffffcbe0

 (void*)(rsp)0xffffffffffffcbe0

 (void*)(temp)0xffffffffffffcbe0

我怀疑这是一个愚蠢的问题,但为什么指针的值会在演员之后发生变化?我试图投射到不同的类型,我总是得到相同的偏移量。 谢谢。

1 个答案:

答案 0 :(得分:2)

  

但是为什么在施法后指针的值会发生变化?

intrspint,不是指针。

"%p"使用int是未定义的行为。

printf("\n (rsp)%p \n", rsp);   // UB
printf("\n (temp)%p \n", temp); // UB

然而,让我们假设转换为unsigned的值是由OP打印的。

printf("\n (rsp)0x%x \n", (unsigned) rsp);   // (rsp)0xffffcbe0
printf("\n (temp)0x%x \n", (unsigned) temp); // (temp)0xffffcbe0

当代码将int指针转换为register int rsp asm("rsp");时,它可能会失去重要性@David Wohlferd。将int转换为指针时,会出现各种转换机制,例如符号扩展,以应对窄int"%p"具有特定于实现的格式。

要明确:OP的代码当然不会打印原始asm("rsp")的地址。 (编译器特定扩展名)。

C提供可选的整数类型(u)intptr_t,它提供从/到等效整数和对象指针的转换。要将对象指针保存为整数,请使用这些类型。不幸的是,C缺少用于打印非void*指针和(u)intptr_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);