是否有任何理由不在C ++中使用按位运算符&,|和^作为“bool”值?

我有时会遇到两个条件中只有一个是真的(XOR)的情况,所以我只是将^运算符抛出到条件表达式中。 我有时也希望评估条件的所有部分是否结果是真的(而不是短路),所以我使用&和|。 我有时也需要累积布尔值,而且&=和| =非常有用。

这样做的时候我已经有了一些眉毛,但代码仍然比其他方面更有意义和更清晰。 是否有任何理由不将这些用于布尔? 是否有任何现代编译器会给出不好的结果?

===============>>#1 票数:49 已采纳

|| &&是布尔运算符,内置函数保证返回truefalse 没有其他的。

| &^是按位运算符。 当你操作的数字域只有1和0时,它们完全相同,但是如果你的布尔值不是严格的1和0 - 就像C语言一样 - 你可能最终会遇到一些行为你不想要。 例如:

BOOL two = 2;
BOOL one = 1;
BOOL and = two & one;   //and = 0
BOOL cand = two && one; //cand = 1

但是,在C ++中, bool类型只能保证为truefalse (分别隐式转换为10 ),因此不需要担心这种立场,而是人们不习惯在代码中看到这样的东西对于不这样做是一个很好的论据。 只要说b = b && x可以了。

===============>>#2 票数:26

两个主要原因。 总之,要仔细考虑; 可能有一个很好的理由,但是如果你的评论中有非常明确的,因为它可能很脆弱,正如你自己说的那样,人们通常不习惯看到这样的代码。

按位xor!=逻辑xor(0和1除外)

首先,如果您使用的值不是falsetrue (或01 ,作为整数),则^运算符可以引入不等于逻辑xor的行为。 例如:

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
}

感谢用户@Patrick首先表达了这一点。

运作顺序

第二, | & ,和^ ,作为按位运算符,不要短路。 此外,在单个语句中链接在一起的多个按位运算符 - 即使使用明确的括号 - 也可以通过优化编译器进行重新排序,因为所有3个操作通常都是可交换的。 如果操作的顺序很重要,这一点很重要。

换一种说法

bool result = true;
result = result && a() && b();
// will not call a() if result false, will not call b() if result or a() false

并不总是给出相同的结果(或结束状态)

bool result = true;
result &= (a() & b());
// a() and b() both will be called, but not necessarily in that order in an
// optimizing compiler

这一点尤为重要,因为您可能无法控制方法a()b() ,或者其他人可能会出现并在以后更改它们而不理解依赖项,并导致令人讨厌的(通常仅发布 - 构建)错误。

===============>>#3 票数:11

我认为

a != b

是你想要的

===============>>#4 票数:10

凸起的眉毛应该足以让你停止这样做。 您不编写编译器的代码,首先为其他程序员编写代码,然后编写代码。 即使编译器工作,令人惊讶的是其他人并不是你想要的 - 按位操作符不是用于bool操作。
我想你也用叉子吃苹果? 它有效,但它给人们带来惊喜,所以最好不要这样做。

===============>>#5 票数:7

bitlevel运算符的缺点。

你问:

“有没有理由不使用按位运算符&| ,和^用于C ++中的“bool”值?

是的, 逻辑运算符 ,即内置的高级布尔运算符! &&|| ,具有以下优点:

  • 保证将参数转换bool ,即01序数值。

  • 保证短路评估 ,一旦最终结果已知,表达式评估就会停止。
    这可以解释为树值逻辑,具有TrueFalseIndeterminate

  • 可读的文本等价物notandor ,即使我自己不使用它们。
    正如读者锑在评论中指出的那样,bitlevel运算符也有替代令牌,即bitandbitorxorcompl ,但在我看来,它们的可读性低于andor not

简而言之,高级运算符的每个这样的优点都是位级运算符的缺点。

特别是,由于按位运算符缺少参数转换为0/1,因此得到例如1 & 20 ,而1 && 2true 也是^ ,按位排他或者,可能以这种方式行为不端。 被视为布尔值1和2是相同的,即为true ,但被视为位图,它们是不同的。


如何表达逻辑要么/或 C ++。

然后,您提供一些问题的背景,

“我有时遇到两种情况中只有一种情况要求为真(XOR)的情况,所以我只是将^运算符抛出一个条件表达式。”

嗯,按位运算符的优先级高于逻辑运算符。 这尤其意味着在诸如的混合表达中

a && b ^ c

你得到了意想不到的结果a && (b ^ c)

而只是写

(a && b) != c

更简明扼要地表达你的意思。

对于多个参数要么/或没有C ++运算符来完成这项工作。 例如,如果你写a ^ b ^ c而不是一个表达“ abc为真”的表达式。 相反它说,“ abc的奇数是真的”,可能是其中1个或全部3个......

要表达一般/或者abcbool类型,只需写

(a + b + c) == 1

或者,使用非bool参数,将它们转换为bool

(!!a + !!b + !!c) == 1


使用&=累积布尔结果。

你进一步阐述,

“我有时也需要积累布尔值,而且&=|=? 可能非常有用。“

嗯,这相当于检查是否满足所有任何条件, de Morgan定律告诉你如何从一个到另一个。 即你只需要其中一个。 原则上你可以使用*=作为&&=符(对于旧的George Boole发现,逻辑AND可以非常容易地表示为乘法),但我认为这会困扰并可能误导代码的维护者。

还要考虑:

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;
}

使用Visual C ++ 11.0和g ++ 4.7.1输出:

true
false

结果不同的原因是bitlevel &=不提供对其右侧参数的bool的转换。

那么,您希望使用哪些结果&=

如果前者为true ,则更好地定义运算符(例如,如上所述)或命名函数,或者使用右侧表达式的显式转换,或者完整地写入更新。

===============>>#6 票数:3

与Patrick的回答相反,C ++没有^^运算符来执行短路异或。 如果你考虑它一秒钟,拥有一个^^运算符无论如何都没有意义:使用exclusive或,结果总是取决于两个操作数。 然而,当比较1 & 21 && 2时,帕特里克关于非bool “布尔”类型的警告同样适用。 一个典型的例子是Windows GetMessage()函数,它返回一个三态BOOL :非零, 0-1

使用&而不是&&| 而不是|| 这不是一个罕见的拼写错误,所以如果你故意这样做,它应该得到一个评论说明为什么。

===============>>#7 票数:2

帕特里克提出了很好的观点,我不打算再重复一遍。 但是我可以建议尽可能通过使用名称很好的布尔变量将'if'语句减少到可读的英语。例如,这是使用布尔运算符,但你可以同样使用按位并适当地命名bool:

bool onlyAIsTrue = (a && !b); // you could use bitwise XOR here
bool onlyBIsTrue = (b && !a); // and not need this second line
if (onlyAIsTrue || onlyBIsTrue)
{
 .. stuff ..
}

您可能认为使用布尔值似乎是不必要的,但它有两个主要方面:

  • 您的代码更容易理解,因为'if'条件的中间布尔值使条件的意图更明确。
  • 如果您使用非标准或意外的代码,例如布尔值上的按位运算符,人们可以更容易地了解您为什么这样做。

编辑:你没有明确表示你想要'if'语句的条件(虽然这似乎很可能),这是我的假设。 但我对中间布尔值的建议仍然存在。

===============>>#8 票数:0

IIRC,许多C ++编译器在尝试将按位操作的结果转换为bool时会发出警告。 您必须使用类型转换才能使编译器满意。

在if表达式中使用按位运算会产生相同的批评,尽管可能不是由编译器引起的。 任何非零值都被认为是真的,所以“if(7&3)”之类的东西都是真的。 在Perl中这种行为是可以接受的,但C / C ++是非常明确的语言。 我认为Spock的眉毛是尽职尽责的。 :)我会追加“== 0”或“!= 0”,以明确你的目标是什么。

但无论如何,这听起来像是个人偏好。 我会通过lint或类似的工具运行代码,看看它是否也认为这是一个不明智的策略。 就个人而言,它看起来像编码错误。

===============>>#9 票数:-1

对bool使用按位运算有助于节省处理器不必要的分支预测逻辑,这是由逻辑运算引入的“cmp”指令产生的。

用位操作替换逻辑(其中所有操作数都是bool)生成更高效的代码,提供相同的结果。 理想情况下,效率应该超过使用逻辑运算在订购中可以利用的所有短路优势。

这可能会使代码有点不可读,尽管程序员应该对其进行评论,理由是为什么这样做。

  ask by Jay Conrod translate from so

未解决问题?本站智能推荐:

2回复

按位AND与函数在C ++中返回bool

我编写了一个程序,列出了一组内容中的错误,并在结尾返回一个布尔值(返回true表示没有找到错误)。 以下是我的代码摘要: 我相信result的价值最终会是正确的。 但是,我想确保调用所有函数checkStuffX() (因为它们在失败时打印错误消息,并且我希望打印所有错误消息)。
3回复

Bitwise Or:C#与C ++

)。 假设你有两个整数,a = 8,b = 2.在C ++ a |中 b是真的。 我使用该行为来处理标志集合。 例如,标志将是1,2,4,8等,并且它们的任何集合都是唯一的。 我无法在C#中找到如何做到这一点,作为| 和&运算符的行为不像在C ++中那样。 我在C#中阅读了有关运算
2回复

C ++中bool值的逻辑“或”效率

第二个if语句是否对所有布尔值执行了一些“或”操作? 把它们视为有字节吗? ex)(0000 | 0000 | 0001)=真...... 或者它是否像Java一样 在布尔值上,它会评估表达式中的每一个bool,即使第一个是真的吗? 我想知道位运算符如何处理bool值。 它
1回复

布尔逻辑“和”和按位运算符“和”的使用

这个问题已经在这里有了答案: 'and'(布尔值)vs'&'(按位)-为什么列表与numpy数组在行为上有所不同? 7个答案 对于这个基本问题感到抱歉,我只是Python编程的初学者。 从我的理解上看,&和“ and”是相同的东西,并且“&”只是“ and”的代
4回复

按位运算符对Java中布尔值的影响

按位运算符应该传输变量并逐位操作它们。 在整数,longs,chars的情况下这是有道理的。 这些变量可以包含由其大小强制执行的所有值。 但是,在布尔值的情况下,布尔值只能包含两个值。 1 =真或0 =假。 但是没有定义布尔值的大小。 它可以大到一个字节或一点点。 那么在布
9回复

什么是按位运算符?

我是一个仅出于娱乐目的而编写代码的人,并且在学术或专业环境中都没有真正地去研究它,因此像这些按位运算符之类的东西真的让我无所适从。 我正在阅读一篇有关JavaScript的文章,该文章显然支持按位操作。 我一直看到该操作在某些地方提到过,并且我尝试阅读以弄清楚它到底是什么,但是我似乎根本
4回复

布尔运算符++和-

今天,在编写一些Visual C ++代码时,我遇到了使我感到惊讶的东西。 似乎C ++支持bool的++(递增),但不支持-(递减)。 这仅仅是一个随机决定,还是背后有某些原因? 这样编译: 这不是:
2回复

C#按位相等的bool运算符

C#中的布尔值是1个字节的变量。 并且因为bool是Boolean类的快捷方式,我希望覆盖&= , | =操作以使它们使用布尔类型,但我不太确定它。 没有像&& =或|| =那样的东西。 这是我的问题,做的事情如下: 会工作,但这只是因为bool将为000000
2回复

分数布尔运算符

我有代码可以比较两个分数类,我的类运算符如下 但是我的输出返回(==),(<=)和(> =)运算符,说它们都是正确的。 在我的main()中 我也尝试过if (fraction1.operator==(fraction2)){而不是if (fraction1 =
3回复

在C ++中使用位运算符或if语句是否更快?

我正在读某个地方,在可能的情况下使用按位运算符代替if语句会更快。 我正在研究一个图像处理项目,我有各种方法可以对像素进行数学运算。 例如,当我添加一个像素时,我会检查并确保总和不会超过最大值。 我把它改成了...... 你们认为它比编写像......这样的陈述更快吗? F