【问题标题】:Creating an integer from three bool values as bits in C++从三个布尔值创建一个整数作为 C++ 中的位
【发布时间】:2012-07-03 21:23:15
【问题描述】:

我有三个代表位的bool 值。我想在表单中有一个整数

true true true = 7
false true false = 2

我有

int val = 4*boolVal1 + 2*boolVal2 + boolVal3;

还有其他方法,也许更简单?

【问题讨论】:

  • 仅供参考,“true true true”不应该是 7 吗?否则到目前为止所有的公式都是错误的......
  • int val = 4*boolVal1 + 2*boolVal2 + boolVal3; 当你有 true true true not 8 时会给出 7
  • 正确,我刚刚发错了。谢谢指正!

标签: c++ c boolean


【解决方案1】:

您可能会发现使用按位运算符比乘法和加法更清晰:

int val = (boolVal1 << 2) | (boolVal2 << 1) | boolVal3; 

【讨论】:

    【解决方案2】:

    除了乘法和位移之外,您还可以使用枚举来记录关系。通常不值得努力,但只是为了完整性......

    enum Encoding
    { 
        Flag3 = 1,      NotFlag3 = 0,
        Flag2 = 1 << 1, NotFlag2 = 0,
        Flag1 = 1 << 2, NotFlag1 = 0
    };
    
    int val = (boolVal1 ? Flag1 : NotFlag1) |
              (boolVal2 ? Flag2 : NotFlag2) |
              (boolVal3 ? Flag3 : NotFlag3);
    

    你到底为什么要为此烦恼?它只是更通用一点,因此您可以稍后更改 Encoding 值,而不必使用实际值触及潜在的分布式代码(例如,如果您意识到与某些文件或网络的格式相比,您会遗漏一点您需要解析的数据,您可以将其添加到一个地方并重新编译)。当然最好还是只提供一个编码/解码函数,如果你要添加新的标志,你仍然需要它。

    虽然拥有 Flag1 和 NotFlag1 可能看起来毫无意义,但通常情况下,您具有相互排斥的值,例如 Sticky 和 ​​Floating,或 Male 和 Female,并且没有特别的理由强迫客户检查 Floating as ! Sticky 或 Female 为 !Male 等。

    【讨论】:

    • NotFlags 在这里不是很有帮助。如果你想知道 Flag2 是否被清除,你仍然会检查(value &amp; Flag2) == NotFlag2。此外,?: 可能会创建比乘法更慢的代码(分支与算术运算)。此外,我发现为此类枚举重载运算符|&amp;^~ 很方便,以便保留类型——我什至有一个宏。
    • @user946850:通常一个函数(尤其是 C 函数)要求调用者从标志中编码一个参数,因此分布式调用代码 - 可以有任意数量,因此其“清洁度”是非常重要,可以很高兴地将标志和“NotFlag”组合在一起,而无需对标志进行测试 - 这是在被调用函数的实现中合并的步骤,因此更容易维护。是的,当枚举在客户端代码中用作适当的值时 - 而不仅仅是用于编码参数 - 适当的运算符是值得拥有的。
    【解决方案3】:

    或者你可以使用霍纳的方法:

    int val = (((boolVal1 &lt;&lt; 1) | boolVal2) &lt;&lt; 1) | boolVal3.

    这也使得在语句中间添加或删除变量更容易,而无需更改所有其他系数。

    但是,这对读者来说可能不太明显。

    【讨论】:

    • 这可能并不重要,但我很好奇 - 对于常见的编译器 - 由于在评估中具有顺序排序,它是否可能表现更差:知道是否有任何/全部会很有趣他们的优化器可以生成可以在 CPU 指令管道上并行化的代码......
    • @Tony,您必须查看机器代码,但我希望现代编译器会注意到括号内没有分支并非常干净地展开。
    【解决方案4】:

    如果您知道字节序,您还可以使用实现定义的行为和位集,小字节序版本:

    union foo {
            unsigned int the_int;
            struct {
                    unsigned int bit3:1
                    unsigned int bit2:1
                    unsigned int bit1:1
            };
    };
    

    然后设置它们:

    foo.bit1 = true;
    foo.bit2 = false;
    foo.bit3 = true;
    

    阅读:

    foo.the_int;
    

    big-endian 版本的位颠倒了,前面有很多填充(如果unsigned int 是 32 位宽,则为 29 位)。

    【讨论】:

      猜你喜欢
      • 2012-05-06
      • 2021-09-29
      • 2014-05-08
      • 1970-01-01
      • 2011-05-02
      • 1970-01-01
      • 1970-01-01
      • 2018-06-13
      • 2017-08-08
      相关资源
      最近更新 更多