【问题标题】:C Pointer Location, Decimal and HexadecimalC 指针位置、十进制和十六进制
【发布时间】:2014-11-20 21:49:48
【问题描述】:

我正在尝试学习如何以十进制和十六进制显示指针值。下面你可以看到我创建了一个值并尝试使用指针打印出值和值位置。

请使代码正常工作,以便打印出十进制和十六进制的值

double val= 1;
printf("The value of val : %f\n",val);


double *ptr;
ptr= &val;

printf("dereference *ptr= %f\n", *ptr);

//Display the location of val with and without pointer use in decimal and hex


//decimal
printf("location of val in decimal with ptr is: %p\n",(void *) ptr); 
printf("location of val in decimal without a pointer is: %p\n",(void *) &val ); 

//hexadecimal THIS IS NOT WORKING 
printf("location of val in hex with ptr is: %#x\n", (void *) ptr); 
printf("location of val in hex without a pointer is: %#x\n", (void *) &val ); 

【问题讨论】:

  • 但是你的问题是什么?
  • 我进行了编辑。基本上我需要将指针位置打印为十进制和十六进制,而十六进制不起作用

标签: c pointers hex decimal


【解决方案1】:

C 通常将内存地址作为十六进制数字返回,因此您只需要使用 %p。至于十进制表示,可以使用类型转换:

int rand1 = 12, rand2 = 15;

printf("rand1 = %p : rand2 = %p\n\n", &rand1, &rand2); 
// returns hexadecimal value of address

printf("rand1 = %d : rand2 = %d\n\n", (int) &rand1, (int) &rand2);  
// returns decimal value of address

【讨论】:

    【解决方案2】:

    不要忘记包含#include <inttypes.h>

    按照 cmets 的建议,最好这样做:

    //hexadecimal
    printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)ptr);
    printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)&val);
    

    如果您对unitptr_t 演员感到不舒服,那么想象您正在演员给unsigned int。这不一样,但这是一个开始。

    更多信息,请阅读this答案。

    另外,您可能想查看%p%x 之间的difference

    【讨论】:

    • 您使用(uintptr_t) 强制转换是正确的。不使用PRIxPTR 等是不正确的。具体来说,在 64 位 Unix 系统上,%x 用于打印 32 位(无符号)整数,但 uintptr_t 是 64 位无符号整数。
    • 我看到乔纳森,感谢您的建议。很高兴学习新事物,这是我的 +1。
    • 请注意,对于标准 C,C99 或 C11 编译器不需要 __STDC_FORMAT_MACROS。几年前,对于 C++ 编译器,似乎有些混乱。 C99 标准(但不是 C11 标准)有一个脚注 182,上面写着:182) 只有在 __STDC_FORMAT_MACROS 定义在 <inttypes.h> 之前,C++ 实现才应该定义这些宏。 这不适用到 C 实现;如果您使用-std=c99-std=c11 或道德等价物进行编译,则应定义<inttypes.h> 中的宏。
    【解决方案3】:

    %p 格式采用 void * 并以实现定义的格式打印它。如果你想夺取控制权,请使用 <stdint.h> 中的类型和 <inttypes.h> 中的格式(最初在 C99 中定义):

    #include <inttypes.h>
    
    printf("Location in decimal:  %" PRIuPTR "\n", (uintptr_t)ptr);
    printf("Location in hex:      0x%.8" PRIXPTR "\n", (uintptr_t)ptr);
    printf("Location in octal     %#" PRIoPTR "\n", (uintptr_t)ptr);
    

    等等

    uintptr_t 类型(名义上是可选的,但所有实际实现都应该定义它)是一个无符号整数类型,它大到足以容纳指向对象的指针(变量;不一定大到容纳函数指针)。 PRIuPTR 等名称为 uintptr_t 类型定义了正确的转换说明符(值是特定于平台的)。

    请注意,如果您使用&lt;inttypes.h&gt;,则无需包含&lt;stdint.h&gt;

    【讨论】:

      【解决方案4】:

      对于十进制使用 %lu (long unsigned) 而不是 %p 此外,不需要使用普通 printf 函数进行 (void *) 强制转换

      像这样:

      //decimal
      printf("location of val in decimal with ptr is: %lu\n",ptr); 
      printf("location of val in decimal without a pointer is: %lu\n",&val );
      

      在以十六进制格式打印指针时,您可以使用 %p 而不是 %x。 像这样:

      //hexadecimal
      printf("location of val in hex with ptr is: %#x\n", ptr); 
      printf("location of val in hex without a pointer is: %p\n", &val ); 
      

      【讨论】:

      • 从技术上讲,需要将%p 转换为void *,因为%p 用于打印void *。现在很少有机器会注意到差异,但我在一台机器上学习了 C,当给定 int i = 0; int *ip = &amp;i; char *cp = (char *)&amp;i; 时,ipcp 中的值在转换为 int 时不一样(它大到足以容纳一个地址)。您的代码在 Win64 平台上无法正常工作;在那里,一个指针是一个 8 字节的数量,但 %lu 需要一个 4 字节的无符号整数。
      • 是的,对于 64 位,最好使用 %llu。但是,指针就是指针,取值或确定大小时需要强制转换。除此之外,应该可以工作。
      猜你喜欢
      • 2011-12-09
      • 2013-01-11
      • 2018-08-26
      • 2015-11-10
      • 2011-06-01
      • 2018-11-07
      • 1970-01-01
      • 2018-07-26
      • 2014-10-30
      相关资源
      最近更新 更多