這看起來是一種永久性問題,但不是你的普通香草大端與小端問題。 ARM有時爲double
使用不尋常的字節順序。從由Jean-米歇爾穆勒,等人:
...最接近 -7.0868766365730135 x 10^-268
由字節 11 22 33 44 55 66 77 88
的在存儲器中的序列編碼的雙精度數「手冊浮點運算的」 (從最低到最高 之一)在x86和Linux/IA-64平臺(他們說是 小端)和88 77 66 55 44 33 22 11
在大多數的PowerPC平臺(他們說是大端 )。一些體系結構,如IA-64,ARM和PowerPC的 據說是雙端的。即它們可能是 是小端或大端,這取決於它們的 配置。
存在一個例外:一些基於ARM的平臺。 傳統上使用的浮點加速器(FPA) 結構中,其中的雙精度數在大端爲了根據 字節序的機器的分解成 兩個32位字並存儲ARM處理器,即一般的小端,意思是 上述數字由序列55 66 77 88 11 22 33 44
編碼。 ARM最近推出了一種浮點運算的新體系結構 運算:矢量浮點運算(VFP),其中字以存儲在處理器的本地字節順序中。
當大端字節順序看,M_PI
將有一個看起來表示這樣的:
0x400921fb54442d18
通過8.6192e+97
近似的大量預示了,看起來表示這樣的:
0x54442d18400921fb
如果仔細觀察,兩個32位字是交換的,但32位字內的字節順序是相同的。顯然,ARM'傳統'雙點格式似乎令Qt庫(或Qt庫配置錯誤)混淆不清。
我不確定處理器是否使用傳統格式,而Qt預計它是VFP格式,或者事情是相反的。但它似乎是這兩種情況之一。
我也不確定如何解決問題 - 我猜想有一些選項可以構建Qt來正確處理這個問題。
下面的代碼片段將至少告訴你的編譯器使用的是什麼格式double
,這可以幫助你縮小哪些需要在Qt的改變:
unsigned char* b;
unsigned char* e;
double x = -7.0868766365730135e-268;
b = (unsigned char*) &x;
e = b + sizeof(x);
for (; b != e; ++b) {
printf("%02x ", *b);
}
puts("");
一個普通的小端機器會顯示:
11 22 33 44 55 66 77 88
更新多一點分析:
目前,我無法對此進行任何真正的調試(我目前甚至無法訪問我的工作站),但通過查看http://qt.gitorious.org上的Qt源文件,可以進行附加分析:
它看起來像Qt調用qlocale.cpp中的QLocalePrivate::doubleToString()
函數來將double
轉換爲字母數字形式。
如果Qt編譯時定義了QT_QLOCALE_USES_FCVT
,那麼QLocalePrivate::doubleToString()
將使用該平臺的fcvt()
函數來執行轉換。如果QT_QLOCALE_USES_FCVT
是而不是定義,那麼QLocalePrivate::doubleToString()
結束呼叫_qdtoa()
執行轉換。該函數直接檢查double
的各個字段,並似乎假設double
處於嚴格的大端或小端形式(例如,使用getWord0()
和getWord1()
函數分別獲取double
的低位和高位字)。
請參閱http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale.cpp和http://qt.gitorious.org/qt/qt/blobs/HEAD/src/corelib/tools/qlocale_tools.cpp或您自己的文件副本以獲取詳細信息。
假設你的平臺是採用傳統的ARM FPA表示爲double
(其中double
的32位半存儲在大端順序不管整個系統是否是小端的),我想你」需要定義QT_QLOCALE_USES_FCVT
來構建Qt。我相信你所需要做的就是在構建Qt時將-DQT_QLOCALE_USES_FCVT
選項傳遞給配置腳本。
我已經添加了一些關於Qt內部似乎正在發生的事情以及我認爲是可能的解決方案。 – 2012-04-14 08:31:32
很好研究。 +1 – 2012-04-16 08:11:24
謝謝您的詳細回覆!其實問題是缺少選項「-DQT_QLOCALE_USES_FCVT」。重建後一切正常。在重建您的代碼片段之前,請打印以下行:'55 66 77 88 11 22 33 44'。 – 2012-04-16 09:41:38