2011-03-23 168 views
9

請您介紹一下這個C程序的輸出結果嗎?我猜想問題在於printf("%d\n",t);函數調用期間堆棧損壞,因爲我推送的是float,但讀取的是int。我不確定。C程序中出現意外結果

#include <stdio.h> 

int main() 
{ 
    long x; 
    float t; 
    scanf("%f",&t); 
    printf("%d\n",t); 
    x=30; 
    printf("%f\n",x); 
    { 
     x=9; 
     printf("%f\n",x); 
     { 
      x=10; 
      printf("%f\n",x); 
     } 
     printf("%f\n",x); 
    } 
    x==9; 
    printf("%f\n",x); 

} 

和輸出

$ ./a.out 
20.39 
0 
20.389999 
20.389999 
20.389999 
20.389999 
20.389999 
$ 
+2

您需要編譯代碼並啓用更多的編譯器警告,並且注意它提供的警告(在將代碼發佈到SO之前)。 – 2011-03-23 09:32:22

+1

@Jonathan Leffler:當我讀到Q時,他知道他做錯了,但想知道實際發生了什麼。儘管如此,他應該更加明確,並且包含編譯器/平臺信息。 – Erik 2011-03-23 09:46:17

回答

1

您使用了錯誤的格式說明打印長。改爲使用格式說明符%ldResults

printf("%f\n",x); 
    //^change this to %ld 
+0

我知道這是錯誤的,我要求輸出的解釋。謝謝無論如何。 – svpranay 2011-03-23 11:22:00

+0

使用錯誤的格式說明符可能會導致標準中所述的@Prasoon引用。因此,結果。 – Mahesh 2011-03-23 11:24:17

9

發生什麼事是你騙編譯器...首先你告訴它你要發送int給printf,但你送一個浮動,而不是,然後你告訴它你要發送double,但您發送long

不這樣做。不要對編譯器撒謊。

您已調用未定義的行爲。任何事情都可能發生。你的程序可能會破壞堆棧;它可能輸出你所期望的;它可能會使檸檬汁從USB端口流出;它可能會使demons fly out of your nose; ...

0

printf("%d\n",t);

printf中使用不正確的格式說明調用未定義的行爲。

打印floatdouble%ld用於打印長

C99使用%f明確表示(WRT printffprintf

如果轉換SPECI網絡陽離子是無效的,行爲是理解過程網絡定義。如果任何參數是 而不是相應轉換規範的正確類型,則行爲爲 未定義。

1

實際發生的是:

  • float爲4個字節,你long爲4個字節,你double爲8個字節。
  • 您通過省略號傳遞float - 將其轉換爲double。 8個字節在堆棧上。
  • 您通過一個long通過省略號 - 堆棧上的4個字節。
  • printf解析堆棧中的8個字節(float說明符),作爲double。此double將包含堆棧中舊「double」的「重要」部分,以及最不重要部分(您的long)中的細微變化。
  • 默認%f輸出截斷值,你看不到變化。

將您所有的%f更改爲例如%.20f以查看long如何影響double

+0

在AMD64上,前八個'float'參數通過SSE寄存器傳遞,所以'long'不會覆蓋它的一部分。 – aaz 2011-03-23 09:47:36

+0

@aaz:行爲匹配x86,所以我做了一件壞事,並假設:) – Erik 2011-03-23 09:48:47

+0

- 它匹配AMD64,所以我假設也是:)儘管'%.20f'的結果會有所不同。 – aaz 2011-03-23 09:52:26