簡體   English   中英

在printf中將變量強制轉換為double會產生隨機輸出

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM