2016-03-27 39 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函數

指針的值被轉換成打印 字符,在一個實現定義方式的序列。

您可以使用調試器確認打印地址是否反映爲有效表示。