检查字节中第 n 位是否已设置的函数

发布于 2024-12-27 13:37:10 字数 116 浏览 0 评论 0原文

我想要一个简单的 C 函数,如果字节中的第 n 位设置为1,它将返回 true。否则会返回 false。

就执行时间而言,这是一个关键函数,因此我正在考虑执行此操作的最佳方法。

I want a simple C function which will return true if the n-th bit in a byte is set to1. Otherwise it will return false.

This is a critical function in terms of execution time, so I am thinking of the most optimal way to do that.

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

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

发布评论

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

评论(7

蓝礼 2025-01-03 13:37:10

以下函数可以满足您的需要:

int isNthBitSet (unsigned char c, int n) {
    static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
    return ((c & mask[n]) != 0);
}

这里假设 8 位字节(C 中未给定),并且第 0 位是最高位。如果这些假设不正确,则只需扩展和/或重新排序 mask 数组即可。

由于您将速度作为最重要的考虑因素,因此没有进行错误检查。不要传入无效的n,这将是未定义的行为。

在疯狂的优化级别 -O3 上,gcc 为我们提供:

isNthBitSet:    pushl   %ebp
                movl    %esp, %ebp
                movl    12(%ebp), %eax
                movzbl  8(%ebp), %edx
                popl    %ebp
                testb   %dl, mask(%eax)
                setne   %al
                movzbl  %al, %eax
                ret
mask:           .byte   -128, 64, 32, 16, 8, 4, 2, 1

非常小且高效。如果您将其设为静态并建议内联,或强制将其作为宏定义内联,您甚至可以绕过函数调用的成本。

只需确保对您提供的任何解决方案进行基准测试,包括这个(a)。优化中的首要原则是“测量,不要猜测!”

如果您想了解按位运算符的工作原理,请参阅此处。简化的仅 AND 版本如下。

仅当在两个源中都设置了两个位时,AND 运算 & 才会在目标中设置一个位。相关表格为:

AND | 0 1
----+----
 0  | 0 0
 1  | 0 1

对于给定的 char 值,我们使用单位位掩码来检查是否设置了某个位。假设您的值为 13,并且您想查看是否设置了从最低有效位起第三位。

Decimal  Binary
  13     0000 1101
   4     0000 0100 (the bitmask for the third-from-least bit).
         =========
         0000 0100 (the result of the AND operation).

您可以看到掩码中的所有零位都会导致等效结果位为零。掩码中的单个一位基本上会让值中的等效位流过结果。如果我们检查的位为零,则结果为零;如果为 1,则结果非零。

这就是 return 语句中的表达式的来源。 mask 查找表中的值都是单位掩码:

Decimal  Binary
  128    1000 0000
   64    0100 0000
   32    0010 0000
   16    0001 0000
    8    0000 1000
    4    0000 0100
    2    0000 0010
    1    0000 0001

(a) 知道我有多好,但你不知道:-)

The following function can do what you need:

int isNthBitSet (unsigned char c, int n) {
    static unsigned char mask[] = {128, 64, 32, 16, 8, 4, 2, 1};
    return ((c & mask[n]) != 0);
}

This assumes 8-bit bytes (not a given in C) and the zeroth bit being the highest order one. If those assumption are incorrect, it simply comes down to expanding and/or re-ordering the mask array.

No error checking is done since you cited speed as the most important consideration. Do not pass in an invalid n, that'll be undefined behaviour.

At insane optimisation level -O3, gcc gives us:

isNthBitSet:    pushl   %ebp
                movl    %esp, %ebp
                movl    12(%ebp), %eax
                movzbl  8(%ebp), %edx
                popl    %ebp
                testb   %dl, mask(%eax)
                setne   %al
                movzbl  %al, %eax
                ret
mask:           .byte   -128, 64, 32, 16, 8, 4, 2, 1

which is pretty small and efficient. And if you make it static and suggest inlining, or force it inline as a macro definition, you can even bypass the cost of a function call.

Just make sure you benchmark any solution you're given, including this one (a). The number one mantra in optimisation is "Measure, don't guess!"

If you want to know how the bitwise operators work, see here. The simplified AND-only version is below.

The AND operation & will set a bit in the target only if both bits are set in the tewo sources. The relevant table is:

AND | 0 1
----+----
 0  | 0 0
 1  | 0 1

For a given char value, we use the single-bit bit masks to check if a bit is set. Let's say you have the value 13 and you want to see if the third-from-least-significant bit is set.

Decimal  Binary
  13     0000 1101
   4     0000 0100 (the bitmask for the third-from-least bit).
         =========
         0000 0100 (the result of the AND operation).

You can see that all the zero bits in the mask result in the equivalent result bits being zero. The single one bit in the mask will basically let the equivalent bit in the value flow through to the result. The result is then zero if the bit we're checking was zero, or non-zero if it was one.

That's where the expression in the return statement comes from. The values in the mask lookup table are all the single-bit masks:

Decimal  Binary
  128    1000 0000
   64    0100 0000
   32    0010 0000
   16    0001 0000
    8    0000 1000
    4    0000 0100
    2    0000 0010
    1    0000 0001

(a) I know how good I am, but you don't :-)

世态炎凉 2025-01-03 13:37:10

只需检查 (1 << bit) & 的值即可字节。如果它非零,则该位被设置。

Just check the value of (1 << bit) & byte. If it is nonzero, the bit is set.

悲喜皆因你 2025-01-03 13:37:10

令数字为num。然后:

return ((1 << n) & num);

Let the number be num. Then:

return ((1 << n) & num);
故人爱我别走 2025-01-03 13:37:10
bool isSet(unsigned char b, unsigned char n) { return b & ( 1 << n); }
bool isSet(unsigned char b, unsigned char n) { return b & ( 1 << n); }
一瞬间的火花 2025-01-03 13:37:10

另一种方法是

    bool isNthBitSet (unsigned char c, int n) {
      return (1 & (c >> n));
    }

Another approach would be

    bool isNthBitSet (unsigned char c, int n) {
      return (1 & (c >> n));
    }
全部不再 2025-01-03 13:37:10
#include<stdio.h>
int main()
{
   unsigned int n,a;
   printf("enter value for n\n");
   scanf("%u",&n);
   pintf("enter value for a:\n");
   scanf("%u",&a);
   a= a|(((~((unsigned)0))>>(sizeof(int)*8-1))<<n);
   printf("%u\n",a);
}   
#include<stdio.h>
int main()
{
   unsigned int n,a;
   printf("enter value for n\n");
   scanf("%u",&n);
   pintf("enter value for a:\n");
   scanf("%u",&a);
   a= a|(((~((unsigned)0))>>(sizeof(int)*8-1))<<n);
   printf("%u\n",a);
}   
哑剧 2025-01-03 13:37:10
#include<stdio.h>

int main() 
{
        int data,bit;
        printf("enter data:");
        scanf("%d",&data);
        printf("enter bit position to test:");
        scanf("%d",&bit);
        data&(1<<bit)?printf("bit is set\n"):printf("bit is clear\n");

   return 0;
}
#include<stdio.h>

int main() 
{
        int data,bit;
        printf("enter data:");
        scanf("%d",&data);
        printf("enter bit position to test:");
        scanf("%d",&bit);
        data&(1<<bit)?printf("bit is set\n"):printf("bit is clear\n");

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