2014-04-07 39 views
2

我偶然發現了這個代碼來檢查楠:本地isnan您在C++

/** 
* isnan(val) returns true if val is nan. 
* We cannot rely on std::isnan or x!=x, because GCC may wrongly optimize it 
* away when compiling with -ffast-math (default in RASR). 
* This function basically does 3 things: 
* - ignore the sign (first bit is dropped with <<1) 
* - interpret val as an unsigned integer (union) 
* - compares val to the nan-bitmask (ones in the exponent, non-zero significand) 
**/ 
template<typename T> 
inline bool isnan(T val) { 
    if (sizeof(val) == 4) { 
     union { f32 f; u32 x; } u = { (f32)val }; 
     return (u.x << 1) > 0xff000000u; 
    } else if (sizeof(val) == 8) { 
     union { f64 f; u64 x; } u = { (f64)val }; 
     return (u.x << 1) > 0x7ff0000000000000u; 
    } else { 
     std::cerr << "isnan is not implemented for sizeof(datatype)==" 
       << sizeof(val) << std::endl; 
    } 
} 

這看起來拱依賴,對不對?但是,我不確定是否存在endianess,因爲無論是小的還是大的endian,float和int都可能以相同的順序存儲。

而且,我不知道是否像

volatile T x = val; 
return std::isnan(x); 

會工作。

這在過去與GCC 4.6一起使用。

回答

1

此外,我不知道是否像std::isnan((volatile)x)這樣的東西會工作。

isnan按值取其參數,所以volatile限定符將被丟棄。換句話說,不,這不起作用。

您發佈的代碼依賴於特定的浮點表示(IEEE)。它還表現出未定義的行爲,因爲它依靠union破解來檢索底層的浮點表示。

在關於代碼審查的說明中,即使我們忽略了前面段落的潛在問題(這是合理的),該函數寫得很糟:爲什麼函數使用運行時檢查而不是編譯時檢查和編譯時錯誤處理?只是提供兩種過載會更好也更容易。

+0

我改變了我的問題,以更清楚地說明我的意思是揮發性的。我也想知道原始問題可能與std :: isnan有什麼關係,以及volatile是否會改變這個問題。 – Albert

+0

@Albert你的編輯不會改變爲什麼'std :: isnan'不能工作的原因。它實際上是相同的代碼。 –

+0

啊我明白了,我誤解了。所以我想知道爲什麼它不起作用,並且它們的功能起作用。另外,爲什麼在這種情況下揮發性物質被丟棄?如果它被內聯,這也是真的嗎?不幸的是,我沒有任何其他參考文獻。 – Albert