2011-11-05 65 views
3

我執行以下代碼奇怪的printf輸出

#include <stdio.h> 

int main() 
{ 
    printf("%f\n", 9/5); 
} 

輸出:0.000000

爲什麼不1

如果我寫printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int));

則輸出爲1.800000 0.000000 4 59

爲什麼不1.800000 4 4 4

我的機器上的sizeof (float)4

在此先感謝

+0

@Shahbaz現在,它不是標籤C++了,真 – MrRap

回答

12

這是因爲你的printf格式說明符不符合你通過它:

9/5int類型。但printf預計float

所以,你需要或者將它轉換爲浮動或作出任何面值的浮動:

printf("%f\n", (float)9/5); 
printf("%f\n", 9./5); 

至於爲什麼你要0.0,這是因爲printf()正在讀1二進制表示(整數)並將其打印爲float。這恰好是一個非常小的非規格化值,非常接近0.0

編輯:還有一些類型的促銷可變參數。

在可變參數函數中,float被提升爲double。因此在這種情況下printf()實際上需要一個持有double的64位參數。但是你只傳遞了一個32位的操作數,所以它實際上是從堆棧中讀取了一個額外的32位(在這種情況下它恰好爲0) - 甚至還有更多未定義的行爲。

+1

當被問及警告時,像GCC這樣的編譯器會發現(使用'gcc -Wall') –

+0

無法保證printf的參數在堆棧上傳遞(或者甚至有堆棧)。你不知道*它在讀什麼。 –

+0

@Stephen佳能:什麼是替代品?可以舉個例子嗎? – jfs

0

內用不正確的格式說明printf是UB。

printf("%f %f %zu %d\n", (float)9/5, 4.0, sizeof(float), sizeof(int)); 

給出正確的輸出。

+1

如何9/5計算爲0 ??! – Shahbaz

+0

9/5是1,你在想5/9。類型不匹配是正確的。 – Kevin

+0

@Shahbaz:我的錯。編輯帖子。 –

0

如果您使用GCC構建,則應該打開-Wall的所有警告,並仔細閱讀它們。

你之所以「奇怪」的輸出爲您違反printf先天條件(參數傳遞,其類型不匹配的格式規範),一旦你做到了,printf自由爲所欲爲,包括崩潰,打印垃圾或熔化CPU。

3

讓我們看看什麼在位級別是怎麼回事:

  • 你計算9/5,這兩個數字int - >此計算結果爲1(再次int)(比方說32位),這是:

    0000 0000 0000 0000 0000 0000 0000 0001 
    
  • 你推它的printf

  • 你告訴printf的參數,以獲得從變元的32位數據並將其打印爲浮點數。
  • printf讀取數我上面寫的,並打印它,就好像它與IEEE 754.結果編碼幾乎爲0。

你可以看到here轉換:

0000 0000 0000 0000 0000 0000 0000 0001 

評估爲

1.4012984e-45 

至於爲何

printf("%f %f %d %d\n", (float)9/5, 4, sizeof(float), sizeof(int)); 

不會產生你所期望的,原因是該參數4int,也就是4個字節(你的機器)。由於參數升級,%f需要一個double這是8個字節。這與上面的問題是一樣的。

+0

但是當我使用float b = 9/5然後打印b的值時,爲什麼我不這樣做。它在這種情況下打印5。你能解釋一下嗎? – chinmayaposwalia

+0

5 ?!這不可能。你需要給我看一段代碼,然後我會告訴你 – Shahbaz

0

9/5是一個整數,但您試圖用「%f」打印它。這是問題的根源。切換到9.0/5或「%d」,你會得到正確的答案。

0

(float)9/5只投9次而不是9/5的結果。所以/操作在這一點上不是一個整數操作。 (浮動)(9/5)將給出1.00000的結果。

嘗試編譯所有警告,它可能會告訴你很多錯誤。

例如一個64位的Linux系統上,用gcc編譯我-Wall得到:

pf.c: In function ‘main’: 
pf.c:6:2: warning: format ‘%f’ expects argument of type ‘double’, but argument 3 has type ‘int’ [-Wformat] 
pf.c:6:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 4 has type ‘long unsigned int’ [-Wformat] 
pf.c:6:2: warning: format ‘%d’ expects argument of type ‘int’, but argument 5 has type ‘long unsigned int’ [-Wformat] 

正如上面提到的,你需要正確的格式說明。使用正確的格式說明和鑄造給出:

#include <stdio.h> 
#include <stdlib.h> 

int main(int argc, char **argv) 
{ 
    printf("%f %f %lu %lu\n",(float)(9/5),(float)4,sizeof(float),sizeof(int)); 
    return 0; 
} 

給出:

[email protected]:~/proj/c=>./pf 
1.000000 4.000000 4 4