简体   繁体   English

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

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

I'm trying to learn how to use the pointer in a C program;我正在尝试学习如何在 C 程序中使用指针; my example is as follows:我的例子如下:

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

I'm trying to print the address of a , the address value inside of p and where the first byte of the tab begins.我正在尝试打印a的地址、 p的地址值以及tab的第一个字节开始的位置。

I can get hexadecimal values when using "%p" , but I'm willing the decimal value of the addresses.使用"%p"时我可以获得十六进制值,但我愿意使用地址的十进制值。

Edit : On this Video image , someone has used "%d" to print a decimal value for a pointer address, and it has confused me.编辑:在此视频图像上,有人使用"%d"打印指针地址的十进制值,这让我感到困惑。

To print a decimal version of an object pointer, 1st convert the pointer to an integer.要打印对象指针的十进制版本,首先将指针转换为整数。 Best to use the optional type uintptr_t .最好使用可选类型uintptr_t

The following type ( uintptr_t ) designates an unsigned integer type with the property that any valid pointer to void can be converted to this type ( uintptr_t ) ... C11dr §7.20.1.4 1以下类型 ( uintptr_t ) 指定一个无符号整数类型,其属性为任何指向 void 的有效指针都可以转换为此类型 ( uintptr_t ) ... C11dr §7.20.1.4 1

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

Then print it.然后打印出来。
Some info on PRIuPTR关于PRIuPTR 的一些信息

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

For pre-C99 code, consider a direct cast to unsigned long .对于 C99 之前的代码,请考虑直接转换为unsigned long @Barmar @巴马尔


OP later commented OP后来评论

"... i will try to manipulate the tab variable , and i will test if every cell in the tab is 4 byte , so may be i will do tab+8 bytes to get the value of a specific cell , here it's a simple example , with decimal it will be easy for me ." “...我将尝试操作选项卡变量,我将测试选项卡中的每个单元格是否为 4 字节,因此我可能会执行 tab+8 字节来获取特定单元格的值,这是一个简单的操作例如,使用十进制对我来说很容易。”

This is a questionable approach as the decimalization of a pointer may not provide the continuous numeric model expected.这是一种有问题的方法,因为指针的十进制化可能无法提供预期的连续数字模型。 This post this may be good for learning, but with OP providing more details in another post, even better ideas could be given for the higher level problem.这篇文章可能对学习有好处,但是随着 OP 在另一篇文章中提供更多详细信息,可以为更高级别的问题提供更好的想法。

First, be aware that addresses are often "number-like" but might not be (eg remember the segment+offset notion of far addresses on 1980-era 16 bits x86 PCs).首先,请注意地址通常是“类似数字的”,但也可能不是(例如,请记住 1980 年代 16 位 x86 PC 上远地址的段+偏移量概念)。

Then, the integral type the most similar to pointers is intptr_t (signed) or uintptr_t (unsigned) - both from <stdint.h> .然后,与指针最相似的整数类型是intptr_t (有符号)或uintptr_t (无符号)——两者都来自<stdint.h>

You might cast that to a long long (hoping that they are not smaller than pointers), eg您可能会将其转换为long long (希望它们不小于指针),例如

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

But really, why do you want to show an address in such a fashion?但说真的,你为什么要以这种方式显示地址? I see no need for it (eg debuggers or linkers are generally showing addresses in hexa, which is probably what %p does).我认为没有必要(例如,调试器或链接器通常以六进制显示地址,这可能是%p所做的)。

Notice that the C11 standard (see n1570 , §7.21.6.2, p315) does not say much about %p for printing pointer:请注意,C11 标准(参见n1570 , §7.21.6.2, p315) %p用于打印指针的%p没有太多说明:

The argument shall be a pointer to void .参数应是指向void的指针。 The value of the pointer is converted to a sequence of printing characters, in an implementation-defined manner.指针的值以实现定义的方式转换为打印字符序列。

I'm understanding the above in a way where printing Hello ⭔ for any pointer would be an acceptable and standard conforming behavior.我以某种方式理解上述内容,其中为任何指针打印Hello ⭔将是一种可接受且符合标准的行为。 In practice, implementations print pointers in a way similar to what linkers and debuggers do, and don't behave in a silly way (but I understand they could).在实践中,实现以类似于链接器和调试器所做的方式打印指针,并且不会以愚蠢的方式运行(但我理解它们可以)。

At last, the actual concrete "numerical" value of a pointer is not really important and can vary greatly from one execution to the next (eg because of ASLR ).最后,指针的实际具体“数字”值并不重要,并且在一次执行和下一次执行之间可能会有很大差异(例如,因为ASLR )。

For printing an "address" (actually a pointer) "%p" is the most common method (note the necessary cast to void* ).对于打印“地址”(实际上是一个指针) "%p"是最常用的方法(注意必要的强制转换为void* )。 If you need the address in decimal instead of hexadecimal, you can convert the pointer into an integral value;如果您需要十进制而不是十六进制的地址,您可以将指针转换为整数值; this is well defined in C (cf. this online C standard draft):这在 C 中有很好的定义(参见这个在线 C 标准草案):

6.3.2.3 Pointers 6.3.2.3 指针

(6) Any pointer type may be converted to an integer type. (6) 任何指针类型都可以转换为整数类型。 Except as previously specified, the result is implementation-defined.除了前面指定的之外,结果是实现定义的。 If the result cannot be represented in the integer type, the behavior is undefined.如果结果不能以整数类型表示,则行为未定义。 The result need not be in the range of values of any integer type.结果不必在任何整数类型的值范围内。

So the code could look as follows:所以代码可能如下所示:

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

If you want to see the pointer as a decimal integer, cast it to unsigned long and print it with %lu format.如果您想将指针视为十进制整数,请将其转换为unsigned long并以%lu格式打印。 While this isn't guaranteed by the standard, it should work in most implementations.虽然标准不能保证这一点,但它应该适用于大多数实现。

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

p is the conversion specifier to print pointers. p 是打印指针的转换说明符。 Use this.用这个。

int a = 42;

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

Remember that omitting the cast is undefined behavior and that printing with p conversion specifier is done in an implementation-defined manner.请记住,省略强制转换是未定义的行为,并且使用 p 转换说明符的打印是以实现定义的方式完成的。

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

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