【问题标题】:Simple way to set/unset an individual bit设置/取消设置单个位的简单方法
【发布时间】:2010-08-06 12:39:05
【问题描述】:

现在我正在使用它来设置/取消设置字节中的各个位:

if (bit4Set)
   nbyte |= (1 << 4);
else
   nbyte &= ~(1 << 4);

但是,你不能用更简单/优雅的方式来做到这一点吗?就像在单个操作中设置或取消设置位一样?

注意:我知道我可以写一个函数来做到这一点,我只是想知道我是否不会重新发明轮子。

【问题讨论】:

标签: c++ bit-manipulation


【解决方案1】:

当然!如果您在代码中扩展 |=&amp;= 会更明显,但您可以这样写:

nbyte = (nbyte & ~(1<<4)) | (bit4Set<<4);

请注意,bit4Set 必须为零或 (不是任何非零值)才能正常工作。

【讨论】:

  • 未设置,然后根据 bit4set 设置。没有想到这一点。谢了。
  • nbyte = (nbyte &amp; ~(1&lt;&lt;4)) | ((!!bit4Set) &lt;&lt; 4) 处理 bit4Set 不为零或一。
【解决方案2】:

将其放入函数中,bool 类型将对所有位值输入强制为 0,1。

int change_bit(int val, int num, bool bitval)
{
    return (val & ~(1<<num)) | (bitval << num);
}

【讨论】:

  • 如果我把它放到一个函数中,我宁愿使用我写的代码。尽管如此,它是正确的。
  • 如果你让编译器在 C++ 中内联这个函数,那么它会像你使用表达式本身一样快,而且你可以获得可读性奖励。
【解决方案3】:

这是一个完全合理且完全标准的成语。

【讨论】:

  • 可能引入了会影响性能的分支。 Pascal Cuoq 的答案可能不太可读,但性能更好。
【解决方案4】:

您是否考虑过为您的位分配助记符和/或标识符,而不是通过数字来引用它们?

例如,假设设置第 4 位会启动核反应堆 SCRAM。我们不将其称为“位 4”,而是将其称为 INITIATE_SCRAM。以下是此代码的外观:

int const INITIATE_SCRAM = 0x10; // 1 << 4

...

if (initiateScram) {
    nbyte |= INITIATE_SCRAM;
} else {
    nbyte &= ~INITIATE_SCRAM;
}

这不一定比您的原始代码更有效(优化后),但我认为它更清晰一些,并且可能更易于维护。

【讨论】:

  • 这几乎是一回事。我实际上是在使用标识符,只是没有将它们放在示例中。
【解决方案5】:
nbyte |= (1 << 4);

如果赋值的右侧(1 &lt;&lt; 4) 始终是这样的常量,那么编译器可能会对其进行优化,因此在生成的汇编中会更简单:

mov r0, _nbyte
mov r1, 10H         ; here is the optimization, no bit shift occured
or r0, r1
st _nbyte, r0

【讨论】:

  • 这是“如何在 nbyte 中设置第 4 位?”问题的答案。问题是“如何根据 bit4Set 的值设置或取消设置 nbyte 中的第 4 位?”
  • 谢谢。我误解了这个问题。我应该删除我的答案吗?
  • 我会给这个答案竖起大拇指,因为即使它不完全正确,它也会增加额外的洞察力,就像帕斯卡所做的那样。
【解决方案6】:

这被标记为 C++,所以您是否考虑过使用 std::bitset 而不是自己进行所有位操作?然后你可以使用数组表示法:bits[3] = bit4Set 来设置适当的位。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-05-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-18
    • 2012-03-26
    • 1970-01-01
    相关资源
    最近更新 更多