在 C++ 中对布尔值使用按位运算符
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24542/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using bitwise operators for Booleans in C++
提问by Jay Conrod
Is there any reason not to use the bitwise operators &, |, and ^ for "bool" values in C++?
是否有任何理由不将按位运算符 &、| 和 ^ 用于 C++ 中的“bool”值?
I sometimes run into situations where I want exactly one of two conditions to be true (XOR), so I just throw the ^ operator into a conditional expression. I also sometimes want all parts of a condition to be evaluated whether the result is true or not (rather than short-circuiting), so I use & and |. I also need to accumulate Boolean values sometimes, and &= and |= can be quite useful.
我有时会遇到我希望两个条件之一为真(XOR)的情况,所以我只是将 ^ 运算符放入条件表达式中。我有时还希望评估条件的所有部分结果是否为真(而不是短路),所以我使用 & 和 |。有时我也需要累积布尔值,&= 和 |= 非常有用。
I've gotten a few raised eyebrows when doing this, but the code is still meaningful and cleaner than it would be otherwise. Is there any reason NOT to use these for bools? Are there any modern compilers that give bad results for this?
这样做时,我有些皱眉,但代码仍然比其他方式更有意义和更清晰。有什么理由不将这些用于布尔值吗?是否有任何现代编译器会为此给出不好的结果?
采纳答案by Patrick
||
and &&
are boolean operators and the built-in ones are guaranteed to return either true
or false
. Nothing else.
||
and&&
是布尔运算符,内置运算符保证返回true
or false
。没有其他的。
|
, &
and ^
are bitwise operators. When the domain of numbers you operate on is just 1 and 0, then they are exactly the same, but in cases where your booleans are not strictly 1 and 0 – as is the case with the C language – you may end up with some behavior you didn't want. For instance:
|
,&
和^
是按位运算符。当您操作的数字域只是 1 和 0 时,它们完全相同,但是在您的布尔值不是严格的 1 和 0 的情况下 - 就像 C 语言的情况 - 您最终可能会出现一些行为你不想要。例如:
BOOL two = 2;
BOOL one = 1;
BOOL and = two & one; //and = 0
BOOL cand = two && one; //cand = 1
In C++, however, the bool
type is guaranteed to be only either a true
or a false
(which convert implicitly to respectively 1
and 0
), so it's less of a worry from this stance, but the fact that people aren't used to seeing such things in code makes a good argument for not doing it. Just say b = b && x
and be done with it.
然而,在 C++ 中,bool
类型保证只有 atrue
或 a false
(它们分别隐式转换为1
and 0
),因此从这种立场来看,不必担心,但事实上人们不习惯在代码中看到这样的东西不这样做是一个很好的论据。只需说b = b && x
并完成它。
回答by Patrick Johnmeyer
Two main reasons. In short, consider carefully; there could be a good reason for it, but if there is be VERY explicit in your comments because it can be brittle and, as you say yourself, people aren't generally used to seeing code like this.
两个主要原因。总之,慎重考虑;可能有一个很好的理由,但是如果您的评论中非常明确,因为它可能很脆弱,而且正如您自己所说,人们通常不习惯看到这样的代码。
Bitwise xor != Logical xor (except for 0 and 1)
按位异或 != 逻辑异或(0 和 1 除外)
Firstly, if you are operating on values other than false
and true
(or 0
and 1
, as integers), the ^
operator can introduce behavior not equivalent to a logical xor. For example:
首先,如果您对false
and true
(或0
and 1
,作为整数)以外的值进行^
运算,则运算符可能会引入与逻辑异或不等效的行为。例如:
int one = 1;
int two = 2;
// bitwise xor
if (one ^ two)
{
// executes because expression = 3 and any non-zero integer evaluates to true
}
// logical xor; more correctly would be coded as
// if (bool(one) != bool(two))
// but spelled out to be explicit in the context of the problem
if ((one && !two) || (!one && two))
{
// does not execute b/c expression = ((true && false) || (false && true))
// which evaluates to false
}
Credit to user @Patrick for expressing this first.
感谢用户@Patrick 首先表达了这一点。
Order of operations
操作顺序
Second, |
, &
, and ^
, as bitwise operators, do not short-circuit. In addition, multiple bitwise operators chained together in a single statement -- even with explicit parentheses -- can be reordered by optimizing compilers, because all 3 operations are normally commutative. This is important if the order of the operations matters.
其次,|
, &
, 和^
作为按位运算符,不会短路。此外,在单个语句中链接在一起的多个按位运算符——即使有显式括号——也可以通过优化编译器重新排序,因为所有 3 个操作通常是可交换的。如果操作顺序很重要,这很重要。
In other words
换句话说
bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false
will not always give the same result (or end state) as
不会总是给出相同的结果(或最终状态)
bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler
This is especially important because you may not control methods a()
and b()
, or somebody else may come along and change them later not understanding the dependency, and cause a nasty (and often release-build only) bug.
这一点尤其重要,因为您可能无法控制方法a()
和b()
,或者其他人可能会在以后不了解依赖项的情况下更改它们,并导致令人讨厌的(通常仅发布构建)错误。
回答by Mark Borgerding
I think
我认为
a != b
is what you want
是你想要的
回答by kokos
The raised eyebrows should tell you enough to stop doing it. You don't write the code for the compiler, you write it for your fellow programmers first and then for the compiler. Even if the compilers work, surprising other people is not what you want - bitwise operators are for bit operations not for bools.
I suppose you also eat apples with a fork? It works but it surprises people so it's better not to do it.
扬起的眉毛应该足以告诉你不要再这样做了。您不是为编译器编写代码,而是先为其他程序员编写代码,然后再为编译器编写代码。即使编译器工作,让其他人感到惊讶也不是你想要的 - 按位运算符用于位操作而不是用于布尔值。
我猜你也用叉子吃苹果?它有效,但它让人们感到惊讶,所以最好不要这样做。
回答by Cheers and hth. - Alf
Disadvantages of the bitlevel operators.
位级运算符的缺点。
You ask:
你问:
“Is there any reason not to use the bitwise operators
&
,|
, and^
for "bool" values in C++? ”
“有什么理由不使用的位运算符
&
,|
以及^
对‘用C布尔’值++?”
Yes, the logical operators, that is the built-in high level boolean operators !
, &&
and ||
, offer the following advantages:
是的,逻辑运算符,即内置的高级布尔运算符!
,&&
和||
,具有以下优点:
Guaranteed conversion of argumentsto
bool
, i.e. to0
and1
ordinal value.Guaranteed short circuit evaluationwhere expression evaluation stops as soon as the final result is known.
This can be interpreted as a tree-value logic, with True, Falseand Indeterminate.Readable textual equivalents
not
,and
andor
, even if I don't use them myself.
As reader Antimony notes in a comment also the bitlevel operators have alternative tokens, namelybitand
,bitor
,xor
andcompl
, but in my opinion these are less readable thanand
,or
andnot
.
保证将参数转换为
bool
,即到0
和1
序数值。保证短路评估,一旦知道最终结果,表达式评估就会停止。
这可以解释为树值逻辑,具有True、False和Indeterminate。可读的文本等价物
not
,and
andor
,即使我自己不使用它们。
作为评论的读者锑笔记也是位级运营商的替代标记,即bitand
,bitor
,xor
和compl
,但在我看来,这些都是小于可读性and
,or
和not
。
Simply put, each such advantage of the high level operators is a disadvantage of the bitlevel operators.
简而言之,高级运算符的每一个优点都是位运算符的缺点。
In particular, since the bitwise operators lack argument conversion to 0/1 you get e.g. 1 & 2
→ 0
, while 1 && 2
→ true
. Also ^
, bitwise exclusive or, can misbehave in this way. Regarded as boolean values 1 and 2 are the same, namely true
, but regarded as bitpatterns they're different.
特别是,由于按位运算符缺少到 0/1 的参数转换,您会得到例如1 & 2
→ 0
,而1 && 2
→ true
。此外^
,按位异或,可能会以这种方式行为不端。视为布尔值 1 和 2 是相同的,即true
,但视为位模式它们是不同的。
How to express logical either/orin C++.
如何在 C++ 中表达逻辑或/或。
You then provide a bit of background for the question,
然后你为这个问题提供一些背景,
“I sometimes run into situations where I want exactly one of two conditions to be true (XOR), so I just throw the ^ operator into a conditional expression.”
“有时我会遇到我希望两个条件中的一个为真(XOR)的情况,所以我只是将 ^ 运算符放入条件表达式中。”
Well, the bitwise operators have higher precedencethan the logical operators. This means in particular that in a mixed expression such as
好吧,按位运算符比逻辑运算符具有更高的优先级。这尤其意味着在混合表达式中,例如
a && b ^ c
you get the perhaps unexpected result a && (b ^ c)
.
你可能会得到意想不到的结果a && (b ^ c)
。
Instead write just
而是只写
(a && b) != c
expressing more concisely what you mean.
更简洁地表达你的意思。
For the multiple argument either/orthere is no C++ operator that does the job. For example, if you write a ^ b ^ c
than that is not an expression that says “either a
, b
or c
is true“. Instead it says, “An odd number of a
, b
and c
are true“, which might be 1 of them or all 3…
对于多参数要么/要么没有完成这项工作的 C++ 运算符。例如,如果你写的a ^ b ^ c
不是“要么a
,b
要么c
是真的”的表达式。相反,它说,“奇数个a
,b
并且c
是真的”,这可能是其中的 1 个或全部 3 个……
To express the general either/or when a
, b
and c
are of type bool
, just write
要表达一般的 or/or when a
,b
and c
are of type bool
,只需写
(a + b + c) == 1
or, with non-bool
arguments, convert them to bool
:
或者,使用非bool
参数,将它们转换为bool
:
(!!a + !!b + !!c) == 1
Using &=
to accumulate boolean results.
利用&=
积累的布尔结果。
You further elaborate,
你进一步阐述,
“I also need to accumulate Boolean values sometimes, and
&=
and|=?
can be quite useful.”
“有时我也需要累积布尔值,
&=
并且|=?
可能非常有用。”
Well, this corresponds to checking whether respectively allor anycondition is satisfied, and de Morgan’s lawtells you how to go from one to the other. I.e. you only need one of them. You could in principle use *=
as a &&=
-operator (for as good old George Boole discovered, logical AND can very easily be expressed as multiplication), but I think that that would perplex and perhaps mislead maintainers of the code.
嗯,这相当于分别检查是否满足所有条件或任何条件,德摩根定律告诉您如何从一个条件到另一个条件。即你只需要其中之一。你可以在原则上使用*=
的&&=
-运算符(如良好的老乔治·布尔发现,逻辑,并且可以很容易地表示为乘法),但我认为,这将困扰和代码可能误导维护者。
Consider also:
还要考虑:
struct Bool
{
bool value;
void operator&=( bool const v ) { value = value && v; }
operator bool() const { return value; }
};
#include <iostream>
int main()
{
using namespace std;
Bool a = {true};
a &= true || false;
a &= 1234;
cout << boolalpha << a << endl;
bool b = {true};
b &= true || false;
b &= 1234;
cout << boolalpha << b << endl;
}
Output with Visual C++ 11.0 and g++ 4.7.1:
使用 Visual C++ 11.0 和 g++ 4.7.1 输出:
true false
The reason for the difference in results is that the bitlevel &=
does not provide a conversion to bool
of its right hand side argument.
结果不同的原因是位级别&=
不提供bool
其右侧参数的转换。
So, which of these results do you desire for your use of &=
?
那么,您希望使用这些结果中的哪些&=
?
If the former, true
, then better define an operator (e.g. as above) or named function, or use an explicit conversion of the right hand side expression, or write the update in full.
如果是前者,true
那么最好定义一个运算符(例如,如上)或命名函数,或者使用右侧表达式的显式转换,或者完整地编写更新。
回答by bk1e
Contrary to Patrick's answer, C++ has no ^^
operator for performing a short-circuiting exclusive or. If you think about it for a second, having a ^^
operator wouldn't make sense anyway: with exclusive or, the result always depends on both operands. However, Patrick's warning about non-bool
"Boolean" types holds equally well when comparing 1 & 2
to 1 && 2
. One classic example of this is the Windows GetMessage()
function, which returns a tri-state BOOL
: nonzero, 0
, or -1
.
与帕特里克的回答相反,C++ 没有^^
用于执行短路异或的运算符。如果您仔细考虑一下,^^
无论如何使用运算符都没有意义:使用异或,结果总是取决于两个操作数。然而,帕特里克关于非bool
“布尔”类型的警告1 & 2
与1 && 2
. 一个典型的例子是 WindowsGetMessage()
函数,它返回一个三态BOOL
:非零、0
、 或-1
。
Using &
instead of &&
and |
instead of ||
is not an uncommon typo, so if you are deliberately doing it, it deserves a comment saying why.
使用&
而不是&&
和|
而不是||
不是一个不常见的错字,所以如果你是故意这样做的,它值得评论说明原因。
回答by genix
Patrick made good points, and I'm not going to repeat them. However might I suggest reducing 'if' statements to readable english wherever possible by using well-named boolean vars.For example, and this is using boolean operators but you could equally use bitwise and name the bools appropriately:
帕特里克提出了很好的观点,我不会重复它们。但是,我是否建议尽可能使用命名良好的布尔变量将“if”语句减少为可读的英语。例如,这是使用布尔运算符,但您同样可以使用按位并适当地命名布尔值:
bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
.. stuff ..
}
You might think that using a boolean seems unnecessary, but it helps with two main things:
您可能认为使用布尔值似乎没有必要,但它有两个主要帮助:
- Your code is easier to understand because the intermediate boolean for the 'if' condition makes the intention of the condition more explicit.
- If you are using non-standard or unexpected code, such as bitwise operators on boolean values, people can much more easily see why you've done this.
- 您的代码更容易理解,因为“if”条件的中间布尔值使条件的意图更加明确。
- 如果您使用的是非标准或意外的代码,例如布尔值上的按位运算符,人们可以更容易地看出您这样做的原因。
EDIT: You didnt explicitly say you wanted the conditionals for 'if' statements (although this seems most likely), that was my assumption. But my suggestion of an intermediate boolean value still stands.
编辑:您没有明确表示您想要“if”语句的条件(尽管这似乎最有可能),这是我的假设。但是我对中间布尔值的建议仍然有效。
回答by spoulson
IIRC, many C++ compilers will warn when attempting to cast the result of a bitwise operation as a bool. You would have to use a type cast to make the compiler happy.
IIRC,许多 C++ 编译器在尝试将按位运算的结果转换为 bool 时会发出警告。您必须使用类型转换才能使编译器满意。
Using a bitwise operation in an if expression would serve the same criticism, though perhaps not by the compiler. Any non-zero value is considered true, so something like "if (7 & 3)" will be true. This behavior may be acceptable in Perl, but C/C++ are very explicit languages. I think the Spock eyebrow is due diligence. :) I would append "== 0" or "!= 0" to make it perfectly clear what your objective was.
在 if 表达式中使用按位运算会引起同样的批评,尽管编译器可能不会这样做。任何非零值都被认为是真的,所以像“if (7 & 3)”这样的东西将是真的。这种行为在 Perl 中是可以接受的,但 C/C++ 是非常明确的语言。我认为 Spock 的眉毛是尽职调查。:) 我会附加 "== 0" 或 "!= 0" 以明确您的目标是什么。
But anyway, it sounds like a personal preference. I would run the code through lint or similar tool and see if it also thinks it's an unwise strategy. Personally, it reads like a coding mistake.
但无论如何,这听起来像是个人喜好。我会通过 lint 或类似工具运行代码,看看它是否也认为这是一个不明智的策略。就个人而言,它读起来像是一个编码错误。
回答by Anoop Menon
Using bitwise operations for bool helps save unnecessary branch prediction logic by the processor, resulting from a 'cmp' instruction brought in by logical operations.
对 bool 使用按位运算有助于节省处理器不必要的分支预测逻辑,这是由逻辑运算引入的“cmp”指令产生的。
Replacing the logical with bitwise operations (where all operands are bool) generates more efficient code offering the same result. The efficiency ideally should outweigh all the short-circuit benefits that can be leveraged in the ordering using logical operations.
用按位运算(其中所有操作数都是 bool)替换逻辑会生成更高效的代码,提供相同的结果。理想情况下,效率应该超过使用逻辑运算在排序中可以利用的所有短路优势。
This can make code a bit un-readable albeit the programmer should comment it with reasons why it was done so.
这会使代码有点不可读,尽管程序员应该对其进行注释并说明这样做的原因。