Anatoly - 1 year ago 70
C Question

# Why value of pointer changes after cast?

Code:

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

Output:

(rsp)0xffffcbe0

(temp)0xffffcbe0

(void*)(rsp)0xffffffffffffcbe0

(void*)(temp)0xffffffffffffcbe0

I suspect this is a silly question, but why does value of pointer changes after cast? I've tried to cast to different types and i always get same offset.
Thank you.

but why does value of pointer changes after cast?

int and rsp are int, not pointers.

Using "%p" is undefined behavior with int.

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

Yet let us assume the value, converted to unsigned was as printed by OP.

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

When code coverts a pointer to int as in register int rsp asm("rsp");, it can lose significance @David Wohlferd. When converting an int to a pointer, various conversion mechanisms occur like sign extension to cope with the narrow int. The "%p" have an implementation specific format.

To be clear: OP's code does not certainly print the address of the original asm("rsp"). (Compiler specific extension).

C provides optional integer types (u)intptr_t that provide a conversion from/to an equivalent integer and object pointer. To save an object pointer in an integer, use those types. Unfortunately, C lacks a latching print specifier for printing the value of a non-void* pointer and (u)intptr_t, thus casting in the following.

#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);
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download