2011-04-13 17 views
1

代碼:如何根據訂購停止printf生成不同的值?

#include <stdio.h> 

int main() 
{ 
    printf(
      " %f, %u, %x,\n", 1.0f, 1.0f, 1.0f); 
    return 0; 
} 

輸出:1.000000,1072693248,0,

代碼:

#include <stdio.h> 

int main() 
{ 
    printf(
      " %x, %f, %u,\n", 1.0f, 1.0f, 1.0f); 
    return 0; 
} 

輸出:3ff00000,0.000000,0

代碼:

#include <stdio.h> 

int main() 
{ 
    printf(
      " %x, %u, %f,\n", 1.0f, 1.0f, 1.0f); 
    return 0; 
} 

輸出:3ff00000,0,1.000000

這只是%u和%x消耗的字節數問題,以及如何讓值變得一致?

回答

3

傳遞參數,它的類型不匹配格式字符串的相應組件會導致不確定的結果,因爲你已經注意到了。特別是,"%x""%u"都期望類型的值(無符號)int。傳遞float(根據ABI,通常實際上會表示爲doublelong double)在語義上不正確。

您的編譯器應該警告您 - 如果沒有,請確保您已啓用所有警告(針對GCC的-Wall)。

如果你想1.0F爲整數,只投:

printf(" %x, %u, %f\n", (unsigned)1.0f, (unsigned)1.0f, 1.0f); 

如果你想獲得二進制表示,嘗試這樣的事情:

float a = 1.0f; 
printf(" %x, %u, %f\n", *((unsigned*)&a), *((unsigned*)&a), a); 
+0

完美。第二個正是我需要的。謝謝。 – deworde 2011-04-13 11:47:54

+0

爲什麼發生這種事情,請參閱http://stackoverflow.com/questions/2941095/convert-ieee-754-float-to-hex-with-c-printf – deworde 2011-04-13 14:07:49

+0

'float'作爲'double'傳遞與ABI無關。這是標準的一部分。變量函數參數總是受到默認促銷的影響,所以不可能將'float','char','short'或'_Bool'(或其任何有符號/無符號變體)作爲可變參數傳遞。 – 2011-09-02 15:02:37

3

您通過第一個參數告訴printf什麼參數:格式字符串。您傳遞給printf 的附加值必須與格式字符串匹配。如果他們不這樣做,你會得到垃圾輸出。在您的示例中,您正在傳遞一個浮點值,並且您正在告訴printf將其視爲一個整數,格式說明符爲%u。你因此得到垃圾輸出。

man page for printf包含您需要爲要打印的值創建正確格式字符串的所有詳細信息。

0

這是參數列表與格式描述符不匹配的問題。如果你想打印1.0F爲整數值,將其轉換爲第一個整數:

printf("%x, %u, %f,\n", (int)1.0f, (int)1.0f, 1.0f); 
1

當我編譯這個與海灣合作委員會我得到以下警告:

crazy.c: In function ‘main’: 
crazy.c:4: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘double’ 
crazy.c:4: warning: format ‘%x’ expects type ‘unsigned int’, but argument 4 has type ‘double’ 
crazy.c:5: warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘double’ 
crazy.c:5: warning: format ‘%u’ expects type ‘unsigned int’, but argument 4 has type ‘double’ 
crazy.c:6: warning: format ‘%x’ expects type ‘unsigned int’, but argument 2 has type ‘double’ 
crazy.c:6: warning: format ‘%u’ expects type ‘unsigned int’, but argument 3 has type ‘double’ 

這就是爲什麼你得到你的垃圾輸出正在使用。用最嚴格的警告進行編譯是一個好主意,這樣您就可以及早發現這樣的問題。

%u%x是期望無符號整數的格式說明符。對於所有示例,您應該使用%f浮點說明符。在給定浮點數的情況下,這總會給出一致的結果。

+1

爲什麼不將這些標誌添加到您的答案以獲得更完整的答案? – Johan 2011-04-13 10:33:04

2

你不能。

每個格式字段的格式都與format-specifier指定的類型完全相同。

在x86系統上,參數通常在堆棧上傳遞,而使用不正確的格式說明符會導致可變參數功能從堆棧中取錯字節數。

對於您的情況,您可以使用3個浮點值調用printf,但將浮點值提升爲double(請參見http://en.wikipedia.org/wiki/Type_conversion#Type_promotion_in_C-like_languages)。
所以在這種情況下(在x86系統上),堆棧上會有3個8字節的字節。

第一格式場將它期望在堆棧上的字節數:

  • %x將需要4個字節
  • %U還將4個字節
  • %F將採取8字節

所以格式字段的順序將影響打印的實際數據。 (使用%f甚至有可能浮點值是無效的,這可能會導致崩潰)。

如果您想了解更多關於可變參數列表,看看答案在Passing of variable arguments in C

+0

這個回答頗具誤導性。沒有理由甚至期望參數在堆棧上傳遞;例如,在x86_64上,它們全都在寄存器中,浮點類型不會被解釋爲整數類型,反之亦然(相反,它們將不可見)。 – 2011-09-02 15:03:37

+0

你說得對。我會將這些信息添加到我的答案中。 – Patrick 2011-09-07 19:15:25