C 测试是否设置了所有高位

C 测试是否设置了所有高位,c,bit-manipulation,C,Bit Manipulation,给定一个只有一个位集(n)的uint16,我想测试位秩是否有所有更重要的位集。我目前正在使用for循环,但我确信有一个聪明的小把戏,只是几个操作符。此代码使用一个编译器,其中位操作产生32位int uint16_t b; // loop variable uint16_t n; // one and only one bit set uint16_t bit_rank; // contains n and possibly higher/lower bits than n for (b = n

给定一个只有一个位集(n)的uint16,我想测试位秩是否有所有更重要的位集。我目前正在使用for循环,但我确信有一个聪明的小把戏,只是几个操作符。此代码使用一个编译器,其中位操作产生32位int

uint16_t b; // loop variable
uint16_t n; // one and only one bit set
uint16_t bit_rank; // contains n and possibly higher/lower bits than n
for (b = n << 1; b < 0x10000; b <<= 1)
    if (b & bit_rank)
        continue;
    else
        break;
if (b == 0x10000)
    printf("all bits from n to 0x8000 are set");
uint16\u t b;//循环变量
uint16\u t n;//一个且仅一个位集
uint16位秩;//包含n位,可能比n位高/低

对于(b=n尝试按n中设置的任何位位置右移(>>)您的位秩。然后,您只有比位秩中该位置更高的有效位。然后反转(~)右移位位的位排列,并测试该值,如果为0,则您知道所有更重要的位都已设置。如果未设置,则并非所有位都已设置。

如果无符号值b正好有一个位集,则将b添加到某个相同类型的无符号值x,并将结果强制转换为该类型(如果小于“int”)如果b或任何更高的位被清除,将产生至少等于b的值,如果b和所有更高的位被设置,将产生小于b的值


请注意,如果b和x的类型小于“无符号”,则在“所有高位集”中将b与x相加case将产生一个太大的结果,无法适应b和x的类型。将结果强制转换或强制为较小的类型将产生一个小于b的值,否则结果将更大。

我现在无法访问编译器,请原谅编译错误, 但以下是我在一般情况下使用的解决方案:

步骤1:准备所需的掩码。这是作为静态变量数组来完成的,以提高性能(函数不需要在每次调用时在堆栈上分配数组)

注意:mask中的每个条目都与您需要的相关n mask相关 掩码[3]是指设置的n位和on位

static masks[17] = { 0b0000000000000000, //this entry is not in use
                     0b1111111111111111, //or use 0xFFFF
                     0b1111111111111110  //or use 0xFFFD
                     0b1111111111111100, //or use 0xFFFB
                     0b1111111111111000, //or use 0xFFF8
                     ...
                     }

                 
现在您可以直接访问您想要的号码

if ( ( bit_rank & mask[n] ) == mask(n) )
    printf( "all bits fron n and on, are set\n" );

另一个简单的解决方案是

((uint16_t) ~bit_rank) < n
((uint16\u t)~bit\u秩)

这是因为对于小于
n
的事物,
n
的位加上所有更高的位需要为零,这意味着
位秩
(假设它包含
n
的位)的所有位都高于
n
的位集。

有效吗?最后一次比较
(b==0x10000)
对我来说似乎有点可疑…(双关语不是故意的)不确定是否完全理解你想要什么,但不是
if(n&bit\u rank==n)
您需要什么?您可以添加具有预期输出的数据样本吗?这样做不会测试是否设置了高于n的位秩中的有效位,它只会测试是否设置了位秩中的第n位如果b是uint16\u t则
b<0x10000
将始终为真,
b==0x10000
始终为假,这比我的答案好得多。所有操作都需要are:
uint16\u t c=bit\u秩+n;如果(c
@4386427不。如果设置了大于n的任何一位,则证明是错误的。@4386427之前我写过你的答案是错误的,但现在我意识到你的解决方案使用了溢出,而且看起来非常正确。谢谢。回答得好。@BSalita这里似乎有点混乱。这个答案是由supercat编写的。不是我写的。我确实发布了一篇文章回答,但再次删除它,因为这个答案比我的好。如果这个答案帮助了你,考虑接受它。@ 4386427我把代码归功于代码。他的答案缺乏代码。这就是为什么你在注释中留下代码。我感谢你们两个,但我更喜欢有标记的答案,因为它同样好的代码,但更健壮的答案。不。d使用这个简单的例子:~(0xffffffff>>1)是0x8000,不是0。看起来像你的答案和4386427的评论同样是好的和聪明的。我把你的答案标记为正确的。@ BSLITITA:如果你的答案是正确的,你就错了这个要求。考虑<代码> n== 1 < /代码>和<代码> BITYRANS==0xFFFE< /COD>。<代码> BITYRADION所有位都高于<代码> N< /代码> SET,B。ut
(uint16\u t)~bit\u rank
是1,它不是
。因此,可能您的需求陈述和问题中的代码都不正确,您的意思是“
bit\u rank
设置了n和所有高阶位”。如果是这样,您应该更正问题(我将删除我的答案,这是针对实际问题中的规范)。问题中
bit_rank
的注释状态为“包含n位,可能比n位高/低”我的解释是,正如你所建议的,
n
中设置的位也被设置在
bit_rank
中。@FalkHüffner完全正确。你必须完整地阅读问题才能形成正确的答案。这是stackoverflow中经常出现的问题。@FalkHüffner:但代码实际上并不是这样做的,因为循环从 b=n