2009-08-18 50 views
5

我真正想要的是|| =運算符。bool與非布爾運算符的行爲

old_value = old_value || possible_new_value; 
old_value ||= possible_new_value; 

第二行是一個編譯器錯誤(C++沒有|| =運算符)。

那麼我的其他選擇是什麼?

old_value += possible_new_value; 
old_value |= possible_new_value; 

雖然我在這個問題上布爾如何與其他非布爾運算符行爲?

- 
-= 
& 
&= 
... 

我可以驗證這些經驗,但我最感興趣的是標準說什麼。

回答

12

根據4.7(積分轉化),第4段,「如果目標類型爲bool,見4.12。如果源類型爲bool,則值false將轉換爲零,並且值true將轉換爲一個。「在4.12中,」算術,枚舉,指針或指向成員類型的指針可以轉換爲類型的右值bool。零值,空指針值或空成員指針值被轉換爲false;任何其他值被轉換爲true「。

bool操作數沒有允許的,但整體的操作數,該bool將被轉換爲一個整數類型。當整數結果被存儲在一個bool變量,它將一個上下文將其轉換爲bool

因此,您將能夠使用+和*作爲布爾或和和,並且您還可以使用|和&也不能脫離它們,因爲(bool1 + bool2 )&如果所有三個變量都是true,則bool3將產生false。((1 + 1)& 1是2 & 1,這是0,或者是假的。)

請記住|和||即使在這裏也不一樣。 |將評估雙方,然後評估按位或。 ||將評估第一個操作數,然後只有當這個錯誤纔會評估第二個操作數。

我不打算討論這裏的風格問題,但如果我做了這樣的事情,我一定會對它發表評論,以便人們知道我在做什麼以及爲什麼。

+0

真棒,謝謝。如果我可以用 – 2009-08-18 17:22:06

+0

+1來引用標準(並回答問題),那麼我會投票兩次,同時也會添加有關樣式 – Gabe 2009-08-18 17:23:09

0

請勿使用|=&=與bools。他們大部分時間都可以工作,但仍然是錯誤的。通常,bool類型只是一個榮耀的int或char。在我曾經使用過的較舊的代碼中,BOOL只是將它定義爲int或char。在這些情況下,如果某些位已被操縱(例如,1&2爲0(false)),則可能得到錯誤的答案。我不確定,但我認爲按位運算符的結果將是一個整數,即使對於布爾。

+0

想法+ =? – 2009-08-18 17:03:47

+3

如果兩個變量都被聲明爲'bool',那麼在什麼情況下(除了破碎的編譯器 - 或者非標準的,也就是預標準編譯器),它們會出錯嗎? – 2009-08-18 17:04:29

+0

如果有任何事情被作爲void *或某事傳遞,並且您有一個使用該類型的API作爲int,則不能保證它們始終將使用「1」作爲true,而不是其他任何非 - 零整數。 – Kip 2009-08-18 17:07:47

0
if (!old_value) 
    old_value = possible_new_value; 

這是原始狀態的直接等價物。它可能會生成更簡單的代碼,因爲它並不總是分配給old_value - 但我不希望性能差異在大型程序中很容易衡量。

0

一個區別是邏輯運算符(如||)保證評估的順序並提供短路,其中按位和算術運算符不這樣做。

我相信編譯器會通過將bools轉換爲應用運算符並轉換回來的數值(0,1)來處理非邏輯運算符。這些轉換由標準嚴格定義,例如:

算術,枚舉,指針或指向成員類型的指針的右值可以轉換爲類型爲bool的右值。將零值,空指針值或空成員指針值轉換爲false,其他任何值都將轉換爲true。

1

你可以使用三元運算符嗎?

old_value = !old_value ? possible_new_value : old_value;

+0

爲什麼會選擇較短的'old_value = old_value || new_value;'? – Kip 2009-08-18 19:22:59

+1

似乎我讀錯了問題:)沒有理由這樣做,而不是'old_value = old_value || new_value;',尤其是因爲後者更具可讀性。 – Cinder6 2009-08-18 21:46:20

0

討厭宏觀兩輪牛車:

#define UPDATE(x) x = x 

UPDATE(old_value) || possible_new_value; 

但我不建議這樣做的。像這樣的宏有幾個原因是一個非常糟糕的主意。

更健全的功能,但沒有短路:

bool set_or(bool &old, bool value) { 
    return (old = old || value); 
} 

... 

bool v = false; 
set_or(v, true); 
+0

當然,這隻有當x是一個變量時才起作用,並且只有在x沒有結束左值時才明顯失敗,並且非常依賴構建宏的一半和一半的表達式。 Ewwwww。 – 2009-08-18 17:17:24

+0

如果評估'possible_new_value'具有副作用,則此宏將失敗。 – 2009-08-18 18:00:30

+0

如果失敗取決於'|| ='的正確語義應該是什麼。我真的不確定短路是否有意或無意。 – sth 2009-08-18 18:18:19

4

標準sayeth:

4.5-4 「整體促銷」

bool類型的右值可以 轉換爲int類型, 的右值與假變爲零和真 成爲一個。

5.17-7 「賦值運算符」

的 形式E1運算的表達式的行爲= E2相當於E1 = E1 E2運算除了E1只計算 一旦。在+ =和 - =中,E1應該具有算術類型,或者是指向完全定義的對象類型的可能合格的 指針。在所有 其他情況下,E1應具有算術 類型。

4.12-1「布爾轉化」

算術,枚舉 指針,或指向構件類型的右值可以 被轉換成類型 布爾的右值。零值,空值指針 值或空成員指針值爲 轉換爲false;任何其他值爲 轉換爲true。

因此,這意味着

b1 += b2 

其中B1和B2是布爾將相當於

b1 = b1 + b2 

和B1和B2將晉升爲0/1整數,然後轉換回到布爾值規則,除了0以外的任何東西都是真的。

所以真值表

 
      true false 
true  true true 
false true false 

所以+ =其實工作並不如|| =根據標準。但是,這可能會讓其他程序員感到困惑,所以我會避免它。

+0

的評論。好的包含5.17-7。 – 2009-08-18 17:22:05

+0

+1用於引用標準,並且用於+ =的明確分解以及用於避免+ =的建議。 – 2009-08-18 17:22:30

0

我相信標準明確定義true和false爲1和0,所以你可以安全地使用位運算符bool值。其他可能被隱式視爲另一個上下文中的bools的類型應該被明確地轉換爲可靠工作。

我見過微軟的編譯器在每次執行這個操作時都會生成一個醜陋的警告,因爲它認爲隱式地將int結果轉換回bool是有危險的。