开发者

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 and position 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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜