【问题标题】:How to check whether exactly one bit is set in an integer?如何检查整数中是否恰好设置了一位?
【发布时间】:2020-04-24 15:32:32
【问题描述】:

我想写一个函数HasOneBit,那个

  • 接受任何整数类型(有符号或无符号,8 到 64 位),
  • 是constexpr,
  • 不调用未定义的行为。

我试图概括这一点:

bool HasOneBit (std::uint64_t value)
{
    return value != 0 && (value & (value - 1)) == 0;
}

如果value 的类型是有符号整数,则会下溢,并且我们将最小值传递给函数。我是否必须重载函数 8 次才能实现所有可能性?

【问题讨论】:

    标签: c++ type-conversion integer


    【解决方案1】:

    以下模板函数满足所有条件 (live demo):

    template <class T>
    constexpr bool HasOneBit (T value)
    {
        static_assert (std::is_integral<T>::value && !std::is_same<T, bool>::value,
                       "This function should be used only with integers.");
    
        const std::make_unsigned_t<T> unsignedValue = value;
    
        return unsignedValue != 0 && (unsignedValue & (unsignedValue - 1)) == 0;
    }
    

    这不会调用未定义的行为,因为value 首先转换为T 的未签名对应项。此转换不会更改value 的位表示。

    我认为,标准中的相关引用是这样的(参见N4713,[conv.integral]#2):

    如果目标类型是无符号的,则结果值是与源整数一致的最小无符号整数(模 2n 其中 n是用于表示无符号类型的位数)。 [注意: 在二进制补码表示中,这种转换是概念性的,位模式没有变化(如果没有截断)。 ——尾注]

    newer version of this rule 更简单。不确定,这是否也适用于无符号到有符号的转换。

    否则,结果是与源整数模2N一致的目标类型的唯一值,其中N为目标类型的宽度。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-12-08
      • 2021-12-20
      • 2011-08-22
      • 1970-01-01
      • 2015-09-23
      • 2011-03-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多