我在C中使用了以下宏:
#define test_bit(_n,_p) !! ( _n & ( 1u << _p))
我研究了宏,但我需要确定宏中双重否定的使用,以及它与宏定义的行为方式不同:
#define test_bit(_n,_p) ( _n & ( 1u << _p))
答案 0 :(得分:10)
考虑测试特定位时会发生什么:
1111 1111 (0xff)
& 0000 0100 (0x04, bit 2)
---- ----
= 0000 0100 (0x04)
如果你这样离开,你的结果就是位掩码本身。
现在考虑对此的双重否定,不与什么都不做相同:
!4 -> 0
!0 -> 1
换句话说,!!4
为您提供1
而不是4
,这可以保证您获得0/1
真值而不是0/whatever-the-bitmask-was
值
以下程序显示了这一点:
#include <stdio.h>
#define test_bit0(_n,_p) (_n & (1u << _p))
#define test_bit1(_n,_p) !!(_n & (1u << _p))
int main (void) {
printf ("%d %d\n", test_bit0 (0xff, 2), test_bit1 (0xff,2));
return 0;
}
并输出:
4 1
正如所料。
除此之外:现在编写代码的地方很少,因为现代编译器不仅可以自动编写代码并选择最有效的方法来执行
((_n & (1u << _p)) != 0)
之类的操作。并且不要让我开始使用obtuse变量名,使用number
和position
提供的可读性远远超过它在编译时丢失: - )
答案 1 :(得分:2)
如果使用某些算术或按位运算符链接宏,它的行为会有所不同。例如,如果你有
#define test_bit(_n,_p) ( _n & ( 1u << _p))
和
test_bit( whatever, 1 ) | test_bit( whatever, 4 )
结果与
的结果不同#define test_bit(_n,_p) !! ( _n & ( 1u << _p))
双重否定只是another way of writing != 0
。
答案 2 :(得分:2)
基本上,双重否定的目的是将宏返回的值约束为0和1.在
中if(test_bit(x, 5)) x=0; // (1)
array[test_bit(x, 5)] = 0; // (2)
在(1)中,两个定义都相同。在(2)中,第一个定义总是设置array[0]
或array[1]
,而第二个定义不设置。