Question about test_bit macro in C
I've used the following macro in C:
#define test_bit(_n,_p) !! ( _n & ( 1u << _p))
I've studied the macro but I need to determine the use of the double negative in the macro, and how it behaves differently from the macro definition :
#define test_bit(_n,_p) ( 开发者_如何学C_n & ( 1u << _p))
Think about what happens when you test a specific bit:
1111 1111 (0xff)
& 0000 0100 (0x04, bit 2)
---- ----
= 0000 0100 (0x04)
If you left it like that, your result would be the bitmask itself.
Now consider the double (logical, not bitwise) negation of that, which is not the same as doing nothing:
first: !4 -> 0
then: !0 -> 1
In other words, !!4
gives you 1
rather than 4
and this guarantees that you will get a 0/1
truth value rather than a 0/whatever-the-bitmask-was
value.
The following program shows this in action:
#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;
}
and it outputs:
4 1
as expected.
Aside: there are precious few places where you would write code like that nowadays since modern compilers are more than up to the task of inlining code automatically, and choosing the most efficient way to do an operation like
((_n & (1u << _p)) != 0)
.And don't get me started on the use of obtuse variable names, the use of
number
andposition
delivers far more in readability that it loses in compile time :-)
It will behave differently if you chain the macro with some arithmetic or bitwise operators. For example if you have
#define test_bit(_n,_p) ( _n & ( 1u << _p))
and
test_bit( whatever, 1 ) | test_bit( whatever, 4 )
the result will differ to the one which you have with
#define test_bit(_n,_p) !! ( _n & ( 1u << _p))
And double negation is just another way of writing != 0
.
Basically, the purpose of double negation is to constrain values returned by the macro to 0 and 1. In
if(test_bit(x, 5)) x=0; // (1)
array[test_bit(x, 5)] = 0; // (2)
In (1), both of the definitions work equivalently. In (2), the first definition always sets array[0]
or array[1]
, whereas the second doesn't.
精彩评论