如何在不使用循环的情况下设置字节中的位

4

我真的很困惑,似乎无法完成简单的任务:

我只需要在字节中设置比特数。

例如:

我需要设置5位。所以我需要0xb00011111

是否有可能不使用循环来完成这个任务?

另外,我也不想写太多的#defines

3个回答

9

对于任何比字长小的整数n,您需要的掩码是:

const unsigned int mask = (1u << n) - 1;

无需使用循环。

一个简单的函数可使用此方式:

unsigned int set_lsbs(unsigned int n)
{
  return (1u << n) - 1;
}

前十个结果如下:
0: 0x0
1: 0x1
2: 0x3
3: 0x7
4: 0xf
5: 0x1f
6: 0x3f
7: 0x7f
8: 0xff
9: 0x1ff

注意:语法0xb00011111不是二进制字面量,其中的“b”只是被解释为十六进制数字。

是的,我只是为了简单起见写了“0xb00011111”。非常感谢! - Bulkin
1
0xb00011111 是有效的C代码,但它并不像原帖作者所期望的那样。 - phuclv
1
哦,没错 0xb00011111 是有效的 C 代码,但是一个非常大的十六进制字面量 :) 作者本意是 0b00011111,但这在 C 中不是有效的,因为 C 不支持二进制字面量。 - Lundin

3
生成一个掩码以设置任何整数类型的最低有效5位,可以这样完成:
mask = ~((~0u) << 5) ;

这将创建一个整数值,其中最低有效的5位设置为1,所有高阶位无论整数类型如何都设置为0。

具体来说,针对所讨论的8位类型:

uint8_t mask = ~((~0u) << 5) ;

为了解释这个过程(忽略比8位更大的中间整数类型):
  • ~0u(零的补码)= 0x11111111
  • 然后移位5位 = 0x11100000
  • 最后取反 = 0x00011111

0
这个能不能不用循环实现呢?
是的,可以在不使用循环的情况下设置给定数字中的n位,但不能随机设置位,只能设置n个连续的位。
要在给定位置设置单个位,请使用以下代码:
   num = num | 1 << pos ;

如果要设置给定数字中的5个连续位,可以使用以下逻辑

num = num | 31 << pos;

这里

31 ==> 1x2^0 + 1x2^1 + .. => 31 is the sum of 5 ones(1 1111)

如果我需要更多的位呢?更多的 case 呢?不,只有两个按位操作就可以使代码相同,快速且容易。 - Bulkin
double pow(float, int); 返回双精度浮点数。你有没有看过你之前的答案?这是非常糟糕的例子和非常糟糕的建议。最好删除它。 - Bulkin
我修改了我的回答。 - Achal

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接