C语言中的位操作和标志测试
假设我有两个C语言中的位操作和标志测试,c,bit-manipulation,flags,bitflags,C,Bit Manipulation,Flags,Bitflags,假设我有两个int类型的变量,a和b,还有一个标志F #define F <something> int a = <something> ; int b = <something> ; 为了测试它们是否都没有,我可以使用以下方法: if ( a & b & F ) if ( !((a & F) || (b & F)) ) 整个测试变成: if ( (a & b & F) && !((a
int
类型的变量,a
和b
,还有一个标志F
#define F <something>
int a = <something> ;
int b = <something> ;
为了测试它们是否都没有,我可以使用以下方法:
if ( a & b & F )
if ( !((a & F) || (b & F)) )
整个测试变成:
if ( (a & b & F) && !((a & F) || (b & F)) )
但这看起来太长太复杂了。有更简单的解决方案吗?可以对“他们都没有”进行测试
合并标志、屏蔽和翻转逻辑
整个测试可以使用xor编写。(感谢马丁·詹姆斯的创意)
这意味着“不是(正是
a
或b
中的一个具有F
)”您正在寻找位相等性,可以通过应用异或运算符^
、反转结果和掩蔽进行测试
a^b
仅当a
和b
的对应位不同时,才将位设置为1。对于相同的对应位,结果位将设置为零
如果你颠倒结果,你会得到位元相等的结果:
~(a ^ b)
剩下的唯一一件事就是用F
屏蔽,并检查是否相等:
if ((~(a ^ b) & F) == F) {
... // All bits indicated by F are set to the same value in a and b
}
也许是这个
!((a & F) ^ (b & F))
非异或…………尽管您想要测试,但为什么要使用
&&
?可能会单独为指令添加测试?是否授权F
中正好有一位为1,或者F
中没有或多个位可以为1?@MikeCAT保证F
为非零。!((a | b)和F)
这是德摩根定律吗?因为我觉得!((a | b)和F)
相当于!((a&F)|(b&F))
而不是!((a&F)| |(b&F))
@BiteBytes无!((a&F)|(a&F))
和!((a&F)|(a&F))
相当于!((a | b)&F)
:前两个都使用a
两次,而最后一个使用a
和b
@BiteBytes(a | b)&F
相当于(a&F)|(b&F)
,并不等同于(a&F)|(b&F)
,不同之处在于|
运算符执行按位或运算,而|
运算符执行逻辑或运算。但是添加
运算符,这不符合逻辑,对于所有运算符,它们都应该是等效的。为什么要检查相等性?如果(~(a^b)&F))就足够了,那么不是吗?如果最后没有相等检查,当某些位(但不一定是所有位)匹配时,您将得到“true”。它也不适用于零的F(当没有检查任何位时,答案应该是“true”)。~(a^b)&F==F
-它是不正确的,它与~(a^b)&1
@dasblinkenlight相同,即使更正了它也会给出最差的代码:)操作符优先级问题:将~(a^b)&F==F)
更改为(~(a^b)&F)==F)
,其可读性明显低于!((a^b)和F)
可读性更强,但可能比多出一个操作码!((a^b)和F)
。另外,由于优雅的对称性,可能会使读者认为它适用于不同的标志,如!((a&F1)^(b&F2))
这不是真的。是的-这是故意的,因为OP正在学习位运算。尽管优化程度不同,但其输出相同。有趣的是,gcc不同于clang在-O0
产生相同的代码,clang不同于gcc在-O2
产生相同的代码,gcc不同于与jmp
@chqrlie共享代码,所选解决方案不起作用:)并在纠正最坏情况时产生代码code@chqrlie我只测试了gcc
if ((~(a ^ b) & F) == F) {
... // All bits indicated by F are set to the same value in a and b
}
!((a & F) ^ (b & F))