【问题标题】:Set bit X of an integer to bit Y of another integer without branching?将一个整数的位 X 设置为另一个整数的位 Y 而不分支?
【发布时间】:2026-01-09 02:30:01
【问题描述】:

下面的copy_bit 函数可以简化为out[out_bit] = in[in_bit] 之类的东西吗? (即不使用if 语句)

template< typename T >
inline void copy_bit( T& out, const T in, const std::size_t out_bit, const std::size_t in_bit )
{
    if ( (in & (1 << in_bit)) != 0 )
    {
        out |= (1 << out_bit); // Set bit
    }
    else
    {
        out &= ~(1 << out_bit); // Clear bit
    }
}

// Set bit 4 in x to bit 11 in y
copy_bit( x, y, 4, 11 );

更新:需要明确的是,这不是作业或 XY 问题,建议 std::bitset 可以回答问题。

【问题讨论】:

  • 好吧,我们不关心家庭作业。我们应该只为实际应用解决问题。
  • @RoeeGavirel 你是对的,但我的意思是 out[out_bit] = in[in_bit] 的那部分。是否有可能“直接”做到这一点?
  • @Alireza: out[out_bit] = in[in_bit] 并不意味着必须直接更改位,因为在 C++ 中您可以重载 operator[]
  • 尚未在任何地方提及,但未定义的行为是由 1 &lt;&lt; in_bit 引起的,如果 in_bit &gt;= CHAR_BIT * sizeof(int) 不管T ;考虑使用static_cast&lt;T&gt;(1),如果T 可能已签名,则转换为T 的未签名版本
  • +1 用于提及 XY 问题 :)

标签: c++ c++11 optimization bit-manipulation branch-prediction


【解决方案1】:

你可以这样做:

//Change the bit if and only if they are not equal:
out ^= (((out >> out_bit) ^ (in >> in_bit)) & 1) << out_bit;

(用 >> 移动两个值,使所需位位于最低有效位置,用 & 仅选择 ^ 操作结果的低位;然后将结果移动到否则为零值的位置^ 与原来的目的地。结果与将in的位in_bit复制到out的位out_bit相同。)

【讨论】:

  • 如果您可以对此进行分析并与原始代码进行比较,则可以加分(很难理解 OP 为什么会提出此请求,除非他认为他可以超越他的编译器以获得性能提升)
  • 我做了最难的部分,让别人做分析(:。无论如何,要求是简化代码而不是优化它。
  • 我不确定很多人会认为这比原始代码更“简单”:)
【解决方案2】:

在一行中这样做的一种方法是首先将输出位重置为零,然后将其与in 数字具有的任何位进行或运算:

(out &= ~(1 << out_bit)) |= (((in >> in_bit) & 1) << out_bit)

【讨论】:

  • 复合赋值运算符太多;很难证明这是否具有未定义的行为。
  • 是的,我自己对序列点感到困惑。我相信我的回答可能确实有未定义的行为。
  • 在 C++03 中它肯定有未定义的行为(对同一个变量的两次赋值,而没有干预序列点),尽管不使用复合赋值很容易解决这个问题
【解决方案3】:

试试这个:

template< typename T >
inline void copy_bit( T& out, const T in, const std::size_t out_bit, const std::size_t in_bit )
{
    out = (out & ~(1 << out_bit)) | (((in & (1 << in_bit)) >> in_bit) << out_bit);
}

解释:

  • (out &amp; ~(1 &lt;&lt; out_bit)) 留下out 中不感兴趣的部分。
  • (in &amp; (1 &lt;&lt; in_bit) 选择in 中有趣的部分
  • (((in &amp; (1 &lt;&lt; in_bit)) &gt;&gt; in_bit) &lt;&lt; out_bit) 将位定位在正确的位置。

【讨论】:

  • 很好的解释,但(((in &amp; (1 &lt;&lt; in_bit)) &gt;&gt; in_bit) &lt;&lt; out_bit) 可以简化为(((in &gt;&gt; in_bit) &amp; 1) &lt;&lt; out_bit),省了一个班次。
最近更新 更多