[英]Why does printf output random values for double and 0.000000 for int?
[英]Variable cast to double in printf produces random output
我試圖查看浮點數的十六進制表示形式,並使用gcc-4.9.2編譯了以下代碼:
#include <stdio.h>
int main()
{
double i = 100;
printf("%f %x\n", i, (double)i);
return 0;
}
我很驚訝地發現,每次運行代碼時,打印出的十六進制值都會改變。 到底是怎么回事? 如何安全地打印浮點數的十六進制表示形式?
%x
格式說明符需要unsigned int
類型的參數。 您正在給它一個double
類型的參數。 該行為是不確定的,這意味着就C標准而言, 任何事情都可能發生-包括更改同一格式字符串中其他說明符的輸出。
要打印浮點數的十六進制表示,請將其復制到unsigned char
數組中並打印該數組的元素。
要打印雙精度的十六進制表示,必須將雙精度轉換為char
數組,然后打印每個字節:
double i = 100;
int j;
for (j=0; j<sizeof(double);j++)
printf("%x\n", ((unsigned char *)&i)[j]);
用((char *)&i)
你把地址i
,並告訴編譯器將其解釋為一個指向char
。 接下來,您將該指針視為char
數組並對其進行索引。
請注意,使用了unsigned char
類型,因此,如果任何字節的最左側位設置為1,則在將其傳遞給int
並將其傳遞給printf
之前,將不會對其進行符號擴展。
格式說明符%x
用於整數類型的對象。 它將相應的參數視為unsigned int類型的對象。 考慮到對於整數類型的參數應用了整數提升。
因此,當說明符用於浮點數時,函數行為是不確定的。
如何安全地打印浮點數的十六進制表示形式?
"%x"
用於unsigned
整數。
要查看FP編號的十六進制表示,請使用"%a"
// mis-match between specifier and argument
// v---------^ v-------^
// printf("%f %x\n", i, (double)i);
double i = 0.1;
printf("%f %a\n", i, i);
輸出量
hexadecimal significant decimal power-of-2 exponent
v-------------v v
0.100000 0x1.999999999999ap-4
或者使用union
union {
double d;
unsigned char uc[sizeof (double)];
} x = {0.1};
for (unsigned i = sizeof x.uc; i > 0;) {
printf("%02X", x.uc[--i]);
}
樣本輸出-取決於字節序和其他平台依賴性。 binary64詳細信息。
+--------------- MS bit: sign
+-+------------- 11 bit: biased exponent
| |+-----------+ 52-bit: raw fraction
| || |
3FB999999999999A
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.