2017-08-25 119 views
3
#include<stdio.h> 

union U{ 
    struct{ 
     int x; 
     int y; 
    }; 
    float xy; 
}; 

int main(){ 
    union U u; 
    u.x = 99; 
    printf("xy %f\n",u.xy); //output " 0 " 
    return 0; 
} 

我已經發現它與float如何被存儲和讀取內部有關。有人可以向我解釋嗎?爲什麼我用C union獲得這個輸出?

+3

用'%f'打印並不是很有用;你應該考慮'%g'或'%e'。如果該值非常小,即使它不爲零,也會打印爲「0.000000」。 (例如,小於「0.0000005」的任何值都將打印爲「0.000000」。)您需要在維基百科上閱讀[IEEE 754](https://en.wikipedia.org/wiki/IEEE_754),例如,瞭解如何表示這些值。例如,在運行使用GCC 7.2.0的macOS Sierra 10.12.5的Mac上,使用'printf(「xy%22.16g \ n」,u.xy);'生成'xy 1.387285479681569e-43'。 –

+0

@JonathanLeffler; OP已經初始化了聯盟'u'的未命名結構的成員'x'。然後他使用不同的聯合成員'xy'來讀取內容。有可能它是一個陷阱表示,在這種情況下,代碼的行爲將是不確定的。 – haccks

+0

4字節'float'中正常數字的範圍通常爲10 +3到10 -3,因此來自'float'的值1.387 ... E-43是一個低於正常值的值(儘管在8字節'雙'值)。 –

回答

-1

原因是該值非常接近於零,所以默認的6位數字 的精度不足以顯示任何內容。

嘗試:

union { int i; float f; } u = {.i= 99}; 

printf("f %g\n", u.f); 
+1

也許你應該展示你得到的東西,並建議在哪裏找到更多信息。 –

+0

或'printf(「xy%.80f \ n」,u.xy);' – 4386427

1

轉換註釋到一個答案。

%f打印不是很有用;你應該考慮%g%e。使用%f時,如果該值非常小,即使它不爲零,也會打印爲0.000000。 (例如,任何小於0.0000005的值都將打印爲0.000000。)例如,您需要閱讀維基百科的IEEE 754以瞭解如何表示這些值。

例如,在Mac運行的MacOS塞拉利昂10.12.5使用GCC 7.2.0,印刷用:

printf("xy %22.16g\n", u.xy); 

生產:

xy 1.387285479681569e-43 

正常數目的以4個字節的範圍float通常爲10 +3到10 -3,所以float的值1.387…E-43是一個低於正常的值(儘管在8字節的值範圍內)。請記住,float傳遞給printf()的值由於「默認參數促銷」而自動提升爲double - printf()從未實際收到float值。

0

表示浮動的方式正在影響結果。請參閱How to represent FLOAT number in memory in Chttps://softwareengineering.stackexchange.com/questions/215065/can-anyone-explain-representation-of-float-in-memory以查看浮點在存儲器中的表示方式。你也沒有初始化結構變量y。它可以具有任何價值。它可能會或可能不會被使用。在你的情況下,這個值非常小,你沒有打印完整的值。要查看floatxy的值,您需要輸出完整值。正如在這裏的評論中所建議的,如果我在Windows的Codeblocks 16.1(包含MinGW編譯器)中使用下面的語句,我會得到與0.000000不同的值。

printf("xy %.80f\n",u.xy); 

給我 XY 0.00000000000000000000000000000000000000000013872854796815689002144922874570169700

0

是的,你說得對,它與浮點值的二進制表示,這是標準的文件IEEE 754 See this great article由史蒂夫Hollasch定義做爲了一個簡單的解釋。 float是一個32位的值,int也是。因此,在你的U結合中,xy正好落在嵌入結構的x成員上,所以當你將x設置爲99時,位1100011(99的二進制表示)將在xy中重新解釋爲浮點數的尾數。正如其他人指出的那樣,這是一個非常小的值,可能會打印爲0,具體取決於printf格式說明符。

從工會成員(X,Y,XY)的命名猜測,我想你想聲明不同的東西,如:

union U 
    { 
    struct 
     { 
     short x; 
     short y; 
     }; 
    float xy; 
    }; 

或者:

union U 
    { 
    struct 
     { 
     int x; 
     int y; 
     }; 
    double xy; 
    }; 

在這些聲明,x和y成員都映射到xy成員上。

相關問題