关于C中test_bit宏的问题

发布于 2024-12-05 02:47:13 字数 244 浏览 0 评论 0原文

我在 C 中使用了以下宏:

#define   test_bit(_n,_p)     !! ( _n & ( 1u << _p))

我已经研究了该宏,但我需要确定宏中双重否定的使用,以及它与宏定义的行为有何不同:

#define   test_bit(_n,_p)     ( _n & ( 1u << _p))

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)     ( _n & ( 1u << _p))

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

递刀给你 2024-12-12 02:47:13

想想当您测试特定位时会发生什么:

  1111 1111 (0xff)
& 0000 0100 (0x04, bit 2)
  ---- ----
= 0000 0100 (0x04)

如果您像这样保留它,您的结果将是位掩码本身。

现在考虑其双重(逻辑,而不是按位)否定,这与不执行任何操作不同:

first: !4 -> 0
 then: !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)

不要让我开始使用迟钝的变量名,使用 numberposition 提供的可读性远高于编译时损失的可读性: -)

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 :-)

南笙 2024-12-12 02:47:13

如果将宏与一些算术或位运算符链接起来,它的行为会有所不同。例如,如果您有

#define   test_bit(_n,_p)     ( _n & ( 1u << _p))

,并且

test_bit( whatever, 1 ) | test_bit( whatever, 4 )

结果将与您的结果不同

#define   test_bit(_n,_p)     !! ( _n & ( 1u << _p))

,并且双重否定只是 另一种编写 != 0 的方式

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.

梦旅人picnic 2024-12-12 02:47:13

基本上,双重否定的目的是将宏返回的值限制为 0 和 1。在

if(test_bit(x, 5)) x=0; // (1)
array[test_bit(x, 5)] = 0; // (2)

(1) 中,这两个定义等效。在 (2) 中,第一个定义始终设置 array[0]array[1],而第二个定义则不然。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文