差异b / w使用%p和%d获取变量的地址

时间:2018-06-30 04:20:09

标签: c get printf

这是一个例子

#include <stdio.h>

int main()
{
    int a;
    printf("%d\n",&a);
    printf("%p\n",&a);

    return 0;
}

======输出=======

-2054871028                                                                                                                      
 0x7ffd8585280c

这两个地址是否指向RAM中的相同地址?

我如何通过使用它们中的每一个,特别是第二个来获得价值。

2 个答案:

答案 0 :(得分:3)

%d格式说明符用于输出带符号的十进制整数。

来自C标准#7.21.6.1p8

  

d,i
  int参数将以[-] dddd格式转换为带符号的十进制。精度指定出现的最小位数;如果要转换的值可以用较少的数字表示,则将其扩展为前导零。默认精度为1。精度为零的零值转换结果为无字符。

%p打印指针。

来自C标准#7.21.6.1p8

  

p
  该参数应为指向void的指针。指针的值以实现定义的方式转换为一系列打印字符。 [强调我的]

此声明

    printf("%d\n",&a);

导致不确定的行为,因为%d对于打印指针无效。

来自C标准#7.21.6.1p9

  

如果转换规范无效,则行为是不确定的。282)如果任何参数不是对应转换规范的正确类型,则行为是不确定的。

答案 1 :(得分:1)

当您通过编写a来获取变量&a的地址时,您实际上所做的就是生成指向a pointer

%p设计用于打印指针。您应该使用%p打印指针。

%d不适用于打印指针。它尝试将其值打印为带符号的十进制数,这可能会造成混淆(如您所见),并且在指针大于整数的机器上,它可能不会打印完整的值。 (例如,如果您尝试在大多数“ 64位”环境中使用%d打印指针,则可能会得到更奇怪的结果-这可能是此处发生的情况的一部分。)

这是一个容易犯的错误。好的编译器应该警告您。我的话说:“警告:格式指定类型为'int',但参数类型为'int *'”。

但是,是的,0x7ffd8585280c-2054871028都“指向RAM中的相同地址”,因为它们都是相同的数字,相同的地址。 (好吧,他们试图成为相同的地址。请参见下面的脚注。)

我不确定您的意思是“以及如何获得价值”。您是要获取指针的值还是指针指向的值?

您已经有了指针的值-它是地址0x7ffd8585280c。并且由于我们知道它指向变量a,所以我们也知道它指向的值。如果这样做,事情将会更加清楚:

int a = 5;
int *ip = &a;
printf("value of pointer: %p\n", ip);
printf("pointed-to value: %d\n", *ip);

没有显式指针变量ip,我们可以编写

int a = 5;
printf("value of pointer: %p\n", &a);
printf("pointed-to value: %d\n", *&a);

但这很愚蠢,因为最后一行等效于更直接的

printf("pointed-to value: %d\n", a);

(使用&来获取变量的地址,然后使用*来获取指针的内容是没有操作的:这很像编写a + 1 - 1。)< / p>


脚注:我说过0x7ffd8585280c-2054871028是相同的数字,但它们不是,只是想成为。 0x7ffd8585280c实际上是-140748133160948,而-2054871028实际上是0x8585280c,是0x7ffd8585280c的低8位数字。看来您机器上的%p默认情况下将指针打印为48位值。令我感到惊讶的是,但是后来我意识到我的Mac也做同样的事情。不知何故我从来没有注意到。