背景:成熟的程序员,重新访问C,除了更好地了解幕后真实情况之外,不是为了任何特定目的。
考虑这个程序。
#include <stdio.h>
int main()
{
//https://stackoverflow.com/questions/2581769/dereference-a-pointer-inside-a-structure-pointer
int concreteInteger = 42;
int* pointerInteger;
pointerInteger = &concreteInteger;
printf("concreteInteger as %%i = %i\n",concreteInteger);
printf("pointerInteger as %%p = %p\n" ,(void*)pointerInteger);
printf("pointerInteger as %%u = %u\n" ,(unsigned)pointerInteger);
printf("*pointerInteger as %%i = %i\n",*pointerInteger);
printf("Done\n");
return 0;
}
当我在OS X 10.11上编译并运行该程序时,我得到以下输出。
$ cc main.c;./a.out
concreteInteger as %i = 42
pointerInteger as %p = 0x7fff5d614878
pointerInteger as %u = 1566656632
*pointerInteger as %i = 42
Done
1566656632
来自哪里?如果我convert 1566656632
to hex我得到0x5D614878
,而不是0x7fff5d614878
。
那么1566656632
来自哪里?我上面做了什么错误的假设?是否将指针作为无符号数字投射在C中未定义的内容?如果是这样,对于奖励积分,如果我想将指针的十六进制地址表示为基数10中的数字,那么最直接的方法是什么?
答案 0 :(得分:1)
将int*
转换为void*
并不会丢失所需的信息来引用数据,因为转换回int*
可以引用concreteInteger
。
将OP int*
转换为unsigned
(32位)仅保留指针地址的32位。
首先尝试%x
并转换为uintptr_t
uintptr_t
位于C99中,是可选类型,但非常常见。
#include <stdint.h>
...
printf("pointerInteger as %%x = %x\n" ,(unsigned)(uintptr_t) pointerInteger);
我期待以下,指针的低32位。 @Chris Turner
pointerInteger as %x = 51af8878
尝试%llx
并首先转换为uintptr_t
以查看更多内容。
printf("pointerInteger as %%llx = %llx\n",
(unsigned long long)(uintptr_t) pointerInteger);
使用<inttypes.h>
中的宏,可以使用匹配的打印说明符直接打印uintptr_t
类型。
printf("pointerInteger %" PRIxPTR "\n", (uintptr_t) pointerInteger);
...将指针的十六进制地址表示为基数10中的数字,这是最直接的方法吗?
指针的地址不是&#34; hex&#34;,它是什么。要显示十进制/十六进制/八进制的指针,请转换为足够宽的整数并使用匹配的打印说明符进行打印。要以便携式打印,请转换为void*
并使用"%p"
,它可以以十六进制打印。
答案 1 :(得分:0)
我将上面的答案标记为最佳,因为它让我得到了我需要的地方,但是下面的程序给了我想要/需要的东西。
#include <stdio.h>
#include <stdint.h>
//needed for the PRI*PTR Macros
#include <inttypes.h>
int main()
{
//#include <inttypes.h>
int concreteInteger = 42;
int* pointerInteger;
pointerInteger = &concreteInteger;
printf("concreteInteger as %%i = %i\n",concreteInteger);
printf("pointerInteger as %%p = %p\n" ,(void*)pointerInteger);
printf("pointerInteger as %%u = %u\n" ,(unsigned)pointerInteger);
printf("*pointerInteger as %%i = %i\n",*pointerInteger);
//as base 10 printf
printf("pointerInteger as %%lu = %lu\n" ,(uintptr_t)pointerInteger);
printf("pointerInteger as %%llu = %llu\n" ,(unsigned long long)(uintptr_t)pointerInteger);
//as hex printf
printf("pointerInteger as %%lx = %lx\n" ,(uintptr_t)pointerInteger);
printf("pointerInteger as %%llx = %llx\n" ,(unsigned long long)pointerInteger);
//using macros from inttypes.h
printf("pointerInteger as %%PRIxPTR = %" PRIxPTR "\n", (uintptr_t) pointerInteger);
printf("pointerInteger as %%PRIxPTR = %" PRIdPTR "\n", (uintptr_t) pointerInteger);
// 140,734,665,721,976
printf("Done\n");
return 0;
}
要带走的几件关键事项。
stdint.h
库来获取(uintptr_t)
类型。 %lu
和%lx
是显示(uintptr_t)
的格式字符串(unsigned long long)
所需的%llu
和%llx