2017-07-18 74 views
-1
#include<stdio.h> 
void main() 
{ 
    int n = 2; 
    printf("%c",&n); 
} 

輸出:L試圖瞭解printf的一個指針有一個char說明符(%C)

在使用%d它當然給出可變n的地址,但它爲什麼使用%c輸出L&

+5

因爲指針不是字符,所以這段代碼是**未定義的行爲**。它也可以做其他任何事情。這是對你的特定環境的一種隨機效應,當printf()的一個指針的一部分在嘗試獲得一個字符轉換爲H時將會評估它... –

+2

我可以聞到UB。唯一發生的事情是UB。 –

+2

呵呵,所以**現在**它*突然*「L」?你覺得現在有什麼不完美嗎? –

回答

-1

這是因爲您告訴printf()函數將int n的地址的前1個字節顯示爲char。

8

它是未定義的行爲因爲您已經使用了錯誤的格式說明符

C11標準:7.21.6.1:第9段:

如果轉換規格是無效,該行爲是 未定義。如果任何參數不是相應轉換規範的正確類型,則行爲是undefined

這意味着如果使用錯誤的格式說明符調用printf會發生任何事情。

4

由於rsp的其他answer表示行爲未定義,任何事情都可能發生。

在你的情況會發生以下情況:

它讀取的&n一個字節,因爲一個字符是一個字節大小其中大部分是8位長的,看到CHAR_BIT explanation on SO。然後它將它打印爲字符。
如果您的機器上的int*int類型相同,則該字節可能是&n的第一個字節。這意味着您的變量n位於地址0x48...(big-endian)或0x...48(little-endian),因爲0x48HAscci code。我假設你的程序正在使用Ascii進行編碼,但這不一定非要。
(您改變了角色從HL但我離開這個答案,因爲它是。)
此外該字節可以在&n中間的某處如果int*超過你的系統的int的大小。

你應該在GCC例如-Wall使更多的警告編譯,您將獲得:

警告:格式「%C」需要類型「詮釋」的說法,但參數2的類型爲「廉政* '[-Wformat =]

在這種情況下你施放該值到char的行爲將被明確限定,但是依賴於實現作爲指針類型的鑄造爲整數被定義實現。

儘管如此,你在做什麼也沒有意義,它不會做的演員。

+1

還有一些不精確的地方(這很容易引發UB):1.)ascii沒有強制要求2.)char'總是**一個字節,但一個字節可能有多於8位3)使用轉換,它不是未定義的,但仍然不是特別有用,因爲指針轉換爲整數類型的結果是*實現定義的* - 仍然是upvoted,解釋是有幫助的! –

+0

@FelixPalmen:謝謝你的解釋! –

+0

答案假設'int'和'int *'是相同的大小,並且'int'和'int *'通過相同的機制傳遞給'printf()'。在C. – chux