簡體   English   中英

我如何習慣性地將BOOL轉換為bool?

[英]How do I idiomatically convert a BOOL to a bool?

<windows.h>標頭帶有自己的BOOL類型。 窺視實現,似乎FALSE只是一個0的宏,而TRUE只是一個宏的1 ,但我不確定這是否已指定。

BOOL轉換為bool的慣用方法是什么? 我可以想象很多可能的方法:

bool a = static_cast<bool>(x);

bool b = x ? true : false;

bool c = (x == TRUE);

bool d = (x != FALSE);

bool e = !!x;

// ...

無需任何明確的轉換:

BOOL x = some_value;
bool b = x;

數字類型的隱式轉換到bool產率false為值0 ,和true對於任何非零值。

順便說一句,你告訴我們<windows.h>如何定義FALSETRUE 它如何定義BOOL (根據你的評論,它是typedef int BOOL;

但是一些編譯器可能會警告這種隱式轉換,即使它是完全有效的代碼。 編譯器可以隨意警告他們喜歡的任何內容,包括用於編寫代碼的丑陋字體。 例如,g ++不會抱怨轉換,即使:

g++ -std=c++11 -pedantic -Wall -Wextra ...

但根據這個在線Visual C ++編譯器 ,VC ++確實產生了一個警告:

warning C4800: 'BOOL' : forcing value to bool 'true' or 'false' (performance warning)

即使使用static_cast ,它仍會產生警告。

您可以使用!!xx ? true : false來避免警告x ? true : false x ? true : false 但我不確定治愈方法是否比疾病更好。

這樣做的簡單而正確的方法就是分配值並依靠隱式轉換來做正確的事情(它會)。

如果你有一個額外的要求來避免編譯器警告,那么這就變成了一個關於Visual C ++而不是C ++語言的問題。 可能還有某種方法可以在不改變來源的情況下禁止某些警告 - 盡管當它們真正有意義時可能會失去同樣的警告。 在評論中,DieterLücking建議:

#pragma warning(disable: 4800) // forcing value to bool 'true' or 'false' (performance warning)

但看起來它仍然需要修改源。 也許有一些不相同的東西。

還有一件事:因為BOOL實際上是int類型,所以提出了這個解決方案:

bool c = (x == TRUE);

不等於其他人。 任何非零int都被視為true,但只有值1 等於 TRUE 如果x == 2 ,則上述將c設置為false ,而if (x)仍將其視為真實條件。 永遠不要將相等的布爾值與trueTRUE (將它們與falseFALSE進行比較更安全,但仍然是不必要的;這就是!運算符的用途。)

這一切都假設如果你有BOOL類型的值,你只關心它是假的還是真的(零或非零)。 不幸的是,情況可能並非總是如此。 正如Ben Voight的回答指出的那樣,Microsoft的API包含至少一個函數GetMessage ,它返回一個不是簡單布爾值的BOOL結果。 在這種可怕的情況下,如果您需要區分多個非零值,則從BOOL轉換為bool是不合適的。

最終,我責怪微軟為一種語言定義 BOOL類型,該語言已經具有完美表現的內置 bool類型。 實際上這不太公平; 它用在需要從C和C ++訪問的API中。 微軟對BOOL的定義可能會回到他們的C實現,它有一定意義 - 至少在C99之前,微軟仍然不支持。 (我不知道微軟的C編譯器是否支持_Bool 。即使它確實如此, _Boolint有一些語義差異,改變BOOL的定義可能會破壞一些代碼 - 特別是使用GetMessage代碼。)

我使用宏:

#define _bool(b) (!!(b)) 

IMO,使我的代碼更具可讀性。

編輯:評論者質疑我在宏名稱中使用下划線。 為了解決這個問題,這里有一個新的版本,它仍然是通用的,仍然使用相同的名稱_bool ,但符合要求,根據

namespace MyBool 
{
    template<typename T> inline bool _bool(const T b) 
    {
        return !!b;
    }
}

using namespace MyBool;

很難說win32程序員會怎么做,但恕我直言應該通過以下方式完成:

bool c = (X == TRUE);

要么

bool d = (x != FALSE);

我認為繼續宏(或任何其他預定義的東西)是一個壞習慣
恆定。

一天TRUE可能變為0而FALSE 1;)

沒有安全的方法,因為Win32 BOOL兩個以上的值

這有點是一個意見問題,但我認為有各種選擇可以有客觀的論據。

最好的選擇是:

bool d = (x != FALSE);

這使得讀者的意圖非常清晰,不依賴於隱式轉換,並且清楚地表明,除了簡單的賦值之外還有更多的事情要做。

第二個最佳選擇是:

bool b = x ? true : false;

但是,對於隨意的讀者來說,這看起來像是重言式。

我嘗試避免在賦值中進行隱式轉換,因為獲取錯誤的轉換是一個令人驚訝的錯誤來源。 即使我知道隱式轉換會做正確的事情,我傾向於明確地做,這可能對將來閱讀代碼的人有所幫助。 顯式還允許您保持啟用轉換警告,以便捕獲您不知道自己(ab)使用的其他隱式轉換。

替代品都有更嚴重的缺點。

bool a = static_cast<bool>(x);

這就像把一個方形釘子敲成一個圓孔。 編寫一個自然返回正確類型的表達式會更優雅。

bool c = (x == TRUE);

TRUE進行比較通常是一個壞主意,因為其他非零值將轉換為false,這幾乎肯定是一個錯誤。

bool e = !!x;

與明確表達您的意思的替代方案相比,太聰明了。 (我在過去做過這件事我感到內疚。)

bool f = x;

性能警告MSVC ++發出純粹的隱式轉換似乎是公平的。 編譯器必須生成額外的代碼才能將int轉換為bool。 裸露的任務對這項額外的工作幾乎沒有任何線索。 如果它處於緊密循環中,你可能會在乎。 (當然, static_cast選項上的性能警告似乎很令人震驚,但我們已經將其視為不那么優雅。)

db表達式清楚地表達了意圖,並且明顯表明這里的內容比直接賦值更多。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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