我想要一个函数,将数字类型的最后一位设置为
n
。例如:1
首先,我有这个实现(
bitmask (5) = 0b11111 = 31
bitmask (0) = 0
只是围绕
mask_t
的typedef
):uint64_t
一切都很好,除了当函数命中
mask_t bitmask (unsigned short n) {
return ((((mask_t) 1) << n) - 1;
}
(
bitmask (64)
的大小)时,然后我得到mask_t
代替设置为bitmask (64) = 0
的64位。所以,我有两个问题:
1
向左推 64 个班次应清除寄存器并保留
1
,然后应用 0
应使用 -1
填充寄存器...
当然,您可以只采用“左移”或“右移”掩码生成,然后对“缺失”进行特殊处理
1
,
n
或者
uint64_t bitmask (unsigned short n) {
if (n == 64) return -((uint64_t)1);
return (((uint64_t) 1) << n) - 1;
}
无论哪种方式都倾向于编译为分支,尽管从技术上讲它并没有有
。 无需
uint64_t bitmask (unsigned short n) {
if (n == 0) return 0;
uint64_t full = ~(uint64_t)0;
return full >> (64 - n);
}
也可以做到(未测试)
if
这里的想法是,我们要么将 1 左移一定量(与原始代码中相同),要么在
uint64_t bitmask (unsigned int n) {
uint64_t x = (n ^ 64) >> 6;
return (x << (n & 63)) - 1;
}
的情况下左移 0。将 0 左移 0 将再次变为 0,减去 1 即可设置所有 64 位。
或者,如果您使用的是现代 x64 平台并且 BZHI 可用,那么速度非常快(BZHI 在实现它的所有 CPU 上都很快)但可移植性有限的选项是:
n = 64
对于
uint64_t bitmask (unsigned int n) {
return _bzhi_u64(~(uint64_t)0, n);
}
来说,这甚至是明确定义的,1的实际计数将是
n > 64
,因为BZHI饱和,但它只读取索引的最低字节。mask_t bitmask (unsigned short n) {
if (n >= 64) {
return ~(mask_t)0;
} else {
return (((mask_t) 1) << n) - 1;
}
}
但是,harold 的答案是如此完整且解释得很好,所以我会选择它作为答案。