2016-03-27 76 views
-1

我在看下面的代码,不知道为什么一个地址没有得到在printf()结印。根据我迄今为止使用指针的经验,下面的printf()语句将打印指针指向的变量的十六进制地址,但在这种情况下,我正在观察不同的行为。当我试图打印出这个指针的内容时,为什么不打印地址?

#include <stdio.h> 

int main (void) 
{ const char * p = "Hello World!"; 

    printf("%p\n", p); 

    return 0; 
} 

而不是地址,我得到输出10968。是什么赋予了?

+1

什么让你觉得'10968'不是一个地址? – CoffeeandCode

+0

你看过[这里](http://stackoverflow.com/questions/14733761/printf-formatting-for-hex)正确格式的十六进制? – skatedan

回答

1

这是可能的10968是一个有效的地址。

要在十六进制打印地址:

#include <stdio.h> 
#include <stdint.h> 

int main(void) 
{ 
    const char *p = "Hello World!"; 
    uintptr_t hexp = p; 
    printf("%#08x\n", hexp); 
    return 0; 
} 
+2

不,'char *'和'void *'具有相同的表示形式。见6.2.5/28。 –

+2

@ n.m。尽管如此,它仍然存在技术上未定义的行为。例如。编译器可以将'char *'在另一个寄存器中传递给'void *'并且仍然符合标准。 –

+0

@ M.M你能详细解释一下吗?如何将参数传递给硬件级别的函数? –

0

你的指针指向你正在运行的可执行文件的.data部分,为您定义什么本质上是一个“常量指针”的角色, ("Hello World!"

由于它指向一个文字,该文字在.data部分的可执行文件中发出,该部分映射到文件的起始位置。除非你使用ASLR/PIE,否则很可能10968是它在进程地址空间中的地址。

格式化(十六进制VS十进制)是在C库级别上定义可能的行为 - 所以这是非常可能的,它仅在十六进制打印指针如果它们是足够高的,例如如果他们指向堆或堆栈空间而不是可执行映射页面。

+0

或者这可能是十六进制,但恰好只包含数字'0-9' –

+0

不,在这种情况下,它将以0x为前缀,%p正常打印。 –

+0

有些文献库放了'0x',有些则不是 –

0

%p输出是实际上实现定义的,所以它可从一个编译器到另一个(应当虽然记载)而变化。根据C11 p7.21.6.1/8 fprintf函数

指针的值被转换成打印 字符,在一个实现定义方式的序列。

您可以使用调试器确认打印地址是否反映为有效表示。