2009-08-21 146 views
73

以這種方式將整數轉換爲布爾值的原因是什麼?爲什麼要用!!將int轉換爲bool時?

bool booleanValue = !!integerValue; 

,而不是僅僅

bool booleanValue = integerValue; 

我所知道的是,在VC++ 7,後者將導致C4800 warning和前不會。兩者之間有沒有其他區別?

+2

我猜問題是,爲什麼前者不會導致C4800要麼因爲即使「鑄造表達爲bool類型不會禁用警告,這是由設計。」 (MS) – Tobias 2009-08-21 15:14:06

+0

嗯,這實際上是它的地方...人們混淆C++和C – 2009-10-22 09:01:38

+2

雙重否定後,值保證是0或1;原始值可能是任何int值。 – 2009-08-21 06:39:32

回答

108

問題與「!!」成語是它很簡潔,很難看,很容易因錯字錯誤,容易丟掉「!」之一,等等。我把它放在「看看我們可以用C/C++多麼可愛」的類別中。

只需編寫bool isNonZero = (integerValue != 0); ......清楚。

+9

+1「bool isNonZero =(integerValue!= 0);」。當代碼使用bool的代碼混合整數,雙精度,ptrs等時,我總是討厭它。他們是不同的類型,應該這樣對待。將bool隱式轉換爲數字類型是一種同時性。 – 2009-08-21 07:13:41

+8

我沒有看到將int/pointers指定爲bools的問題 - 這是一個C/C++庫存語言,任何熟悉它們的開發者都應該知道它。然而,有時候你想避免編譯器警告等等 - 在這種情況下,一個明確的比較(或者一個強制轉換)肯定比相對難懂的'!!'技巧更可取。 – 2009-08-21 07:26:48

+0

Ints和bools是不同的。爲什麼應該0 = false。這是布爾型之前的日子的宿醉。這也意味着!! a並不一定等於反直覺。 – 2009-08-21 07:43:09

13

因爲!integerValue裝置integerValue == 0和!! integerValue從而意味着integerValue!= 0,有效的表達式返回一個布爾值。後者是一個信息丟失的演員。

49

從歷史上看,使用了!!成語,以確保您的布爾真的包含預期的bool樣變量的兩個值之一,因爲C和C++沒有一個真正的bool類型,我們用int小號僞造了。這與現實中的「真實」bool s不太一樣。

但使用!!是記錄(編譯器和未來的任何人在你的代碼的工作都),是的,你真的打算到int轉換爲bool的有效手段。

+9

如果OP甚至不明白它的含義,我不會說「有效的記錄手段」。一個更好的方法是static_cast (integerValue)。 – arolson101 2009-08-21 13:41:12

+10

OP可能不知道「List 」的含義,或者是'|| ='。 '!!'在C和C++領域中是一個非常非常根深蒂固的成語。如果有人不知道,他/她應該學習 - 然後對是否使用它做出自己的合理評估。 – 2009-08-21 15:19:13

+5

'bool var =(bool)intVar;'?有什麼問題? – bobobobo 2009-12-04 15:48:11

5

一個bool只能有兩個狀態,0和1的整數。可以具有從-2147483648任何狀態到2147483647假定一個符號的32位整數。一元!如果輸入爲0,則操作員輸出1,如果輸入爲除0之外的任何其他輸出,則輸出0.所以!0 = 1且!234 = 0。簡單地切換輸出所以0變爲1,1變爲0

所以第一個語句保證的booleanValue將被設置爲等於0或1和爲任何其他值,第二條語句沒有。

+2

這是完全錯誤的。第二個語句涉及一個隱式的'int'->'bool'類型轉換。這是很好定義的,任何非零的'int'都將被轉換爲'true',並且0將被轉換爲'false'。 VC++給出的警告實際上是一個「性能警告」,與此無關。 – 2009-08-21 07:28:11

+0

我認爲你讓BOOL和bool混淆。用bool,你會得到一個真正的bool,並且有一個隱式的轉換,因此是真的還是假的。 – Recep 2009-08-21 10:36:46

+2

C++中bool的狀態不是1和0,但是是true和false。 – 2009-08-21 16:08:49

-1

沒有什麼大的理由,除了是偏執狂或通過代碼,它的一個布爾大喊大叫。

對於編譯器來說,它最終不會有所作爲。

+0

生成的代碼可能會「較慢」:整數將需要測試以查看它是否爲零。但是,對於表示爲0/1二進制的布爾值,不需要測試。 – 2009-08-21 16:10:45

+2

但是,有了這個理性,我們應該對每個虛擬函數調用都有一個性能警告...... – gimpf 2009-12-04 16:16:09

+0

您可能想要閱讀:http://stackoverflow.com/a/1847949/62921 – ForceMagic 2013-08-02 02:22:05

-2

我從來不喜歡轉換爲bool數據類型的這種技術 - 它的氣味錯了!

相反,我們使用了一個名爲boolean_cast方便的模板中找到here。這是一個靈活的解決方案,它在它在做什麼更加明確,可以使用如下:

bool IsWindow = boolean_cast<bool>(::IsWindow(hWnd)); 
+8

這有點矯枉過正不是嗎?我的意思是在一天結束時轉換爲布爾是精度的損失,並歸結爲類似 返回b?真假; 這與大約相同!! TRUE個人而言,這是過度工程化的類STL戀物癖。 – 2009-08-21 12:18:07

+0

我認爲你不同意使用boolean_cast然後(因此投票) - 那麼你會建議我們使用什麼呢? – Alan 2009-08-21 13:57:24

+4

我建議你使用這個語言,因爲它是用來表示的。高性能,令人討厭。只需削減學士學位,並完成工作。 – 2009-10-22 09:11:18

4

!!是轉換爲bool的慣用方式,和它的作品閉嘴的Visual C++編譯器的sillywarning關於這種所謂的低效率轉換。

我看到其他的答案和評論,很多人不熟悉Windows編程這個成語的實用性。這意味着他們沒有做過任何嚴肅的Windows編程。並且盲目地假設他們遇到的是代表性的(不是)。

#include <iostream> 
using namespace std; 

int main(int argc, char* argv[]) 
{ 
    bool const b = static_cast<bool>(argc); 
    (void) argv; 
    (void) b; 
} 
 
> [d:\dev\test] 
> cl foo.cpp 
foo.cpp 
foo.cpp(6) : warning C4800: 'int' : forcing value to bool 'true' or 'false' (performance warning) 

[d:\dev\test] 
> _ 

而且至少有一人認爲,如果一個絕對新手,不承認它的意義,那麼它的解精。那很愚蠢。有許多新手不認識或理解。寫一個人的代碼,以便任何新手都能理解它,這不是專業人士所需要的。甚至沒有學生。從排除新手無法識別的操作員和操作員組合的路徑開始......好吧,我沒有給出這種方法的適當描述的話,對不起。

乾杯&心連心,

13

它的使用,因爲C語言(和一些預標準的C++編譯器太)不具備bool類型,只是int。因此,int s用於表示邏輯值:0應該表示false,其他所有內容都是true!運營商從00返回1。雙!被用來反轉這些,並在那裏確保該值取決於其邏輯值只是01

在C++中,由於引入了合適的bool類型,因此不再需要這樣做。但是你不能只更新所有的遺留源,而且你不應該因爲C和C++的向後兼容(大部分時間)。但是許多人仍然這樣做,出於同樣的原因:保持他們的代碼與舊編譯器向後兼容,舊編譯器仍然不理解bool s。

這是唯一真正的答案。其他答案是誤導性的。

+0

很明顯。 +1 :) – zx81 2014-05-24 00:53:51

6

另一個選項是這似乎產生的彙編代碼一行少三元運算符(在Visual Studio 2005反正):其產生彙編代碼

bool ternary_test = (int_val == 0) ? false : true; 

cmp DWORD PTR _int_val$[ebp], 0 
setne al 
mov BYTE PTR _ternary_test$[ebp], al 

對戰:

bool not_equal_test = (int_val != 0); 

其中產生:

xor eax, eax 
cmp DWORD PTR _int_val$[ebp], 0 
setne al 
mov BYTE PTR _not_equal_test$[ebp], al 

我知道這不是一個巨大的差異,但我很好奇它,只是認爲我會分享我的發現。

1

user143506的答案是正確的,但對於一個可能的性能問題我相比,ASM的possibilies:

return x;return x != 0;return !!x;甚至return boolean_cast<bool>(x)結果在這一套完美的彙編指令:

test edi/ecx, edi/ecx 
setne al 
ret 

這已經過GCC 7.1和M​​SVC 19 2017測試。(只有MSVC 19 2017中的boolean_converter會導致更多的asm代碼,但這是由模板化和結構引起的,並且可以通過性能角度來忽略,因爲同樣的林如上所述,可能只是爲了不同的功能而使用相同的運行時間進行復制。)

這意味着:沒有性能差異。

PS:使用此boolean_cast:

#define BOOL int 
// primary template 
template< class TargetT, class SourceT > 
struct boolean_converter; 

// full specialization 
template< > 
struct boolean_converter<bool, BOOL> 
{ 
    static bool convert(BOOL b) 
    { 
    return b ? true : false; 
    } 
}; 

// Type your code here, or load an example. 
template< class TargetT, class SourceT > 
TargetT boolean_cast(SourceT b) 
{ 
    typedef boolean_converter<TargetT, SourceT> converter_t; 
    return converter_t::convert(b); 
} 

bool is_non_zero(int x) { 
    return boolean_cast<bool>(x); 
} 
相關問題