C++有逻辑运算,!a
,a && b
,a || b
适用于真/假值。还有位运算,适用于所有(整数?)类型、~a
、a & b
、a | b
、a ^ b
、(a << N
,a >> N
),再加上原地变异算子a &= b
,a |= b
,a ^= b
,(a <<= b
,a >>= b
)。
让我困惑的是,位操作可能作用于bool
中根本不属于真/假值的位,甚至是不必要的位操作。我想最后一个事实使得位移位对于bool
来说是未定义的,这让我怀疑是否所有的位操作都是有效的。
那么,对于布尔类型~a == !a
,a && b == a & b
,a || b == a | b
,这些等价吗?
由于某种原因(这里不会质疑),没有"原地"* 逻辑 * 变异操作符(即a &&= b
、a ||= b
)。
这引发了以下问题:这些其他的位运算对布尔值本身有效吗?a &= b
和a |= b
是否总是分别等价于a = a && b
和a = a || b
?**(没有"就地"异或a = a ^ b
?)
一些例子:https://godbolt.org/z/hcccG8c9o
1条答案
按热度按时间ffx8fchx1#
(For简单性我将假设C20,即整数类型的2的补码表示。我所写的东西在技术上可能不适用于C20之前所有理论上可能一致的整数类型表示。)
令我困惑的是,按位运算可能作用于根本不属于真/假值的bool位。
内置的按位运算首先将 * 通常的算术转换 * 应用于其操作数。对于包含 * 整数提升 * 的整数操作数:转换等级低于
int
的操作数首先转换为int
(如果int
不能保存原始类型的所有值,则转换为unsigned int
或更高等级的整数类型)。升级始终保持原始值不变。对于
bool
,true
Map到1
,false
Map到0
。因此,升级后的结果将设置或取消设置其最低有效位,而所有其他位都将取消设置。此外,始终至少有15
个此类位。因为X1 M10 N1 X必须至少为16位宽。因此,
~a == !a
始终为假。~
将设置这些附加位,而!a
的提升不会。然而,只有当a
为false
时,bool(~a) == bool(!a)
才为true
,因为设置了附加位时,bool(~a)
始终为true
。a && b == a & b
始终为真,因为当应用&
时,附加位将为零。a || b == a | b
总是为真,因为附加位将再次保持为零。但是,如果
a
和b
是实际表达式,则还有另一个区别,即逻辑运算符会缩短求值,而按位运算符不会,因此副作用可能不同。此外,逻辑运算符的结果将是
bool
,而按位运算符的结果将是int
。因此,它们不可互换,因为它们可能例如影响使用其结果的重载分辨率。而且,这只适用于内置运算符。如果涉及任何重载运算符,则没有任何保证。