如何生成n位无符号掩码?避免n等于类型位宽时的未定义行为
符合C++标准的全1掩码构造方法
要构造一个n位全1的无符号整数掩码(支持n等于该类型的位宽),可以用以下完全符合标准且无需条件判断的写法:
#include <cstddef> #include <type_traits> template <typename T> constexpr T all_set_mask(unsigned int n) noexcept { static_assert(std::is_unsigned_v<T>, "模板参数T必须是无符号整数类型"); // ~T{} 生成该类型全1的数值,右移 (总位宽 - n) 位得到低n位全1的掩码 return ~T{} >> (sizeof(T) * CHAR_BIT - n); }
原理说明
~T{}:对于无符号类型T,默认初始化的T{}是0,按位取反后得到该类型所有位均为1的数值(比如unsigned类型就是0xFFFFFFFFu),这一步完全符合C++标准。- 右移操作:无符号整数的右移是逻辑右移(高位补0),当
n等于类型位宽时,sizeof(T)*CHAR_BIT - n等于0,右移0位直接返回全1的数值;当n小于位宽时,右移后低n位保留全1,高位补0,正好得到目标掩码。 - 无未定义行为:右移的位数范围是
0到sizeof(T)*CHAR_BIT -1,完全符合C++标准中对无符号整数右移的要求(右移位数必须小于类型的位宽),不存在未定义行为。
示例验证
- 当
T=unsigned,n=5时:sizeof(unsigned)*CHAR_BIT=32,右移32-5=27位,~0u >>27结果为0b11111u,符合预期。 - 当
T=unsigned,n=32时:右移0位,结果为0xFFFFFFFFu,即全32位1,符合需求。
简化写法(针对特定类型)
如果不需要适配任意无符号类型,针对unsigned可以简化为:
constexpr unsigned all_set_mask(unsigned int n) noexcept { return ~0u >> (sizeof(unsigned) * CHAR_BIT - n); }
内容的提问来源于stack exchange,提问作者Bernard
相关产品推荐
相关产品推荐

