2011-11-20 62 views
2

我在windows7上使用dev cpp編譯我的代碼。將int打印爲float時,printf的行爲是什麼?

int d = 0x12; 
char* e = (char*)&d; 
printf("%d %d\n", sizeof (int), sizeof (float)); 
printf("%p %p\n", &d, (float*)&d); 
printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]); 
printf(" %d | %x | %#1x | %#1x | %#1x |%p\n", d, e[0], e[1], e[2], e[3], &e[0]); 
getchar(); 

4 4 
0028FF40 0028FF40 
0028FF40 0028FF40 0028FF41 0028FF42 0028FF43 
18 | 12 | 0 | 0 | 0 |0028FF40 

你可以看到,如果我使用%d打印d,它會打印e的4個字節。但是如果我使用下面的%f,它會在必須打印e的第一個字節的地方顯示零。任何人都可以幫助解釋爲何發生這種情況爲什麼e的內容取決於d如何格式化?

int d = 0x12; 
char* e = (char*)&d; 
printf("%d %d\n", sizeof (int), sizeof (float)); 
printf("%p %p\n", &d, (float*)&d); 
printf("%p %p %p %p %p\n", &d, &e[0], &e[1], &e[2], &e[3]); 
printf(" %f | %x | %#1x | %#1x | %#1x |%p\n", d, e[0], e[1], e[2], e[3], &e[0]); 
getchar(); 

的輸出是:

4 4 
0028FF40 0028FF40 
0028FF40 0028FF40 0028FF41 0028FF42 0028FF43 
0.000000 | 0 | 0 | 0 | 0x28ff40 |76869F1D 
+3

您應該停止使用Dev-Cpp。它非常過時,並使用古代版本的GCC。 – ThiefMaster

+0

爲什麼你將'(int *)'轉換爲'(float *)'?編程很難,因爲它沒有這樣的東西。 –

+0

[如果printf被錯誤的格式字符串調用會發生什麼?](http:// stackoverflow。com/questions/14504148/what-c​​an-happen-if-printf-is-called-with-a-wrong-format-string) –

回答

8

未定義的行爲。

在實踐中,你看到的可能是由於這樣的事實,%f使得printf從參數列表,這是8個字節*double。但d只有4個字節大小,所以現在一切都沒有對齊。

請記住,printf是一個可變參數函數,這意味着它是完全非類型安全的; printf必須在沒有編譯器幫助的情況下從堆棧中提取原始字節。完全取決於您確保參數與格式字符串完全對應。


*可能。

+0

我認爲你的答案意味着e的字節仍然存在,但它只是它從錯誤的地方讀取它們。我可以通過在下一行中製作一個鑄造的printf來進行驗證。 printf(「%f |%x |%#1x |%#1x |%#1x |%p \ n」,(float)d,e [0],e [1],e [2],e [3 ],&e[0]); 這實際上給出了正確的結果。感謝您的解釋。 – ada

1

是的,你正在從堆棧中取出8個字節 - 其中四個是0x00000012,其餘依賴於編譯器(可能是在構建printf的堆棧幀時被壓入堆棧的返回地址)。

2

您正在通過自動類型促銷絆倒。

您似乎認爲自sizeof(int)== sizeof(float)以來,您可以將d作爲float或int交替傳遞。但事情是,在C中你不能傳遞一個浮點數。

在C中,當在表達式中使用char或short時,它會自動轉換爲int。同樣,當您在表達式中使用float時,它會自動轉換爲double。

因此,當您執行printf(「%f」,d)時,編譯器會在進行函數調用之前將一個int,即四個字節推入堆棧。然後在函數中,printf()看到「%f」,並從堆棧中取出八個字節。其中四個字節是你的「d」,另外四個字節是在那裏發生的。在你的例子中,e [0]和e [1]。

如果要將「d」打印爲浮點數,則需要明確地將其轉換爲浮點型變量或將其分配給浮點型變量。無論哪種情況,編譯器都會在調用printf()之前將其轉換爲double。 (注意:聽起來很奇怪,「%f」用於打印雙精度數據,而不是浮點數,不能打印浮點數,可以用「%f」和「%lf」來讀浮點數或雙精度浮點數。 scanf(),但在printf()中,「%f」打印雙打。)

+0

informative thanks。:) – ada

+0

*「當您在表達式中使用float時,它會自動轉換爲double。」*這是錯誤的。除非表達式中的其他操作數是雙精度(*常用算術轉換*),否則浮點不會在所有表達式中隱式轉換爲double。你所追求的是什麼*默認參數促銷*,只有當A)float被傳遞給沒有原型的函數時,纔會發生** B)float被傳遞給帶有可變參數的函數(原型以',..結尾.. .. .')。 – user694733