繁体   English   中英

如何在C程序中打印指针的地址值?

[英]How to print the address value of a pointer in a C program?

我正在尝试学习如何在 C 程序中使用指针; 我的例子如下:

   #include <stdio.h>
   #include <stdlib.h>
   
   int main(int argc, char *argv[]) {
        int * tab = (int*)malloc(sizeof(int)*5);
        int a = 10;
        int *p;
        p  = &a;
        printf("the address of a is %d \n",&a);    
        printf("the address of a using the pointer is %p \n",p);    
        printf("the address of tab is %d \n",tab);    
    }

我正在尝试打印a的地址、 p的地址值以及tab的第一个字节开始的位置。

使用"%p"时我可以获得十六进制值,但我愿意使用地址的十进制值。

编辑:在此视频图像上,有人使用"%d"打印指针地址的十进制值,这让我感到困惑。

要打印对象指针的十进制版本,首先将指针转换为整数。 最好使用可选类型uintptr_t

以下类型 ( uintptr_t ) 指定一个无符号整数类型,其属性为任何指向 void 的有效指针都可以转换为此类型 ( uintptr_t ) ... C11dr §7.20.1.4 1

#include <inttypes.h>
uintptr_t d = (uintptr_t)(void *) &a;

然后打印出来。
关于PRIuPTR 的一些信息

printf("%" PRIuPTR "\n", d);

对于 C99 之前的代码,请考虑直接转换为unsigned long @巴马尔


OP后来评论

“...我将尝试操作选项卡变量,我将测试选项卡中的每个单元格是否为 4 字节,因此我可能会执行 tab+8 字节来获取特定单元格的值,这是一个简单的操作例如,使用十进制对我来说很容易。”

这是一种有问题的方法,因为指针的十进制化可能无法提供预期的连续数字模型。 这篇文章可能对学习有好处,但是随着 OP 在另一篇文章中提供更多详细信息,可以为更高级别的问题提供更好的想法。

首先,请注意地址通常是“类似数字的”,但也可能不是(例如,请记住 1980 年代 16 位 x86 PC 上远地址的段+偏移量概念)。

然后,与指针最相似的整数类型是intptr_t (有符号)或uintptr_t (无符号)——两者都来自<stdint.h>

您可能会将其转换为long long (希望它们不小于指针),例如

 printf("address of a in decimal is %lld\n", (long long) (intptr_t) (&a));

但说真的,你为什么要以这种方式显示地址? 我认为没有必要(例如,调试器或链接器通常以六进制显示地址,这可能是%p所做的)。

请注意,C11 标准(参见n1570 , §7.21.6.2, p315) %p用于打印指针的%p没有太多说明:

参数应是指向void的指针。 指针的值以实现定义的方式转换为打印字符序列。

我以某种方式理解上述内容,其中为任何指针打印Hello ⭔将是一种可接受且符合标准的行为。 在实践中,实现以类似于链接器和调试器所做的方式打印指针,并且不会以愚蠢的方式运行(但我理解它们可以)。

最后,指针的实际具体“数字”值并不重要,并且在一次执行和下一次执行之间可能会有很大差异(例如,因为ASLR )。

对于打印“地址”(实际上是一个指针) "%p"是最常用的方法(注意必要的强制转换为void* )。 如果您需要十进制而不是十六进制的地址,您可以将指针转换为整数值; 这在 C 中有很好的定义(参见这个在线 C 标准草案):

6.3.2.3 指针

(6) 任何指针类型都可以转换为整数类型。 除了前面指定的之外,结果是实现定义的。 如果结果不能以整数类型表示,则行为未定义。 结果不必在任何整数类型的值范围内。

所以代码可能如下所示:

int main(int argc, char *argv[]) {
    int a =10;
    int *p = &a;
    p  = &a;

    unsigned long long addrAsInt = (unsigned long long)p;

    printf("the adress of a is %llu \n",addrAsInt);
    printf("the adress of a using the pointer is %p \n",(void*)p);
}

如果您想将指针视为十进制整数,请将其转换为unsigned long并以%lu格式打印。 虽然标准不能保证这一点,但它应该适用于大多数实现。

printf("the address of a is %lu\n", (unsigned long)&a);    

p 是打印指针的转换说明符。 用这个。

int a = 42;

printf("%p\n", (void *) &a);

请记住,省略强制转换是未定义的行为,并且使用 p 转换说明符的打印是以实现定义的方式完成的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM