代码之家  ›  专栏  ›  技术社区  ›  Phidelux

以std::bitset访问std::uint8\t

  •  0
  • Phidelux  · 技术社区  · 6 年前

    我想在C/C++中建模状态登记,它应该是可访问的。 std::bitset std::uint8_t . 因此,我将把它们结合起来如下:

    #include <bitset>
    #include <iostream>
    
    union byte {
            std::uint8_t uint;
            std::bitset<8> bitset;
    };
    
    int main(int, char*[])
    {
            byte b = { .uint = 0b10101010 };
    
            std::cout << "Value of bit 5: "
                    << (b.bitset.test(5) ? "true" : "false") << std::endl;
    
            std::cout << "Value of bit 4: "
                    << (b.bitset.test(4) ? "true" : "false") << std::endl;
    
            std::cout << "Bitset Output: " << b.bitset << std::endl;
            std::cout << "Uint Output: " << static_cast<int>(b.uint) << std::endl;
    
            return 0;
    }
    

    GCC x86_64 8.2 . 但是,我想知道我是否可以期望这在所有情况下都能工作,或者我是否更适合使用一些助手函数,比如 bitset bittest , ...

    2 回复  |  直到 6 年前
        1
  •  4
  •   Dan M.    6 年前

    你想在这里做什么 union in this SO answer ),因此即使在同一个编译器上也不能保证它正常工作。

    而且,即使允许, std::bitset<8> 不保证具有与 std::uint8_t (事实上,它在任何主要编译器上都不存在)。

    对你来说,你可以用普通的 标准::位集<8> 具有 to_ulong 方法。

    另一种选择是使用具有位集成员的包装器类,该类将提供方便的方法来分配/转换到 uint8_t .

    ,这可能是一个好主意(如果您想保持类的大小为1字节) 标准:uint8\t test )手动。

        2
  •  2
  •   Scheff's Cat    6 年前

    我听了某个节目主持人的评论

    至于您的问题,如果您想要一个既可以作为本机uint8\t又可以以“好”的方式处理位的类型,那么您必须自己实现这样一个类。如果您需要它映射到内存映射硬件寄存器,它可能应该包装一个指向寄存器的指针。

    #include <cassert>
    #include <iostream>
    #include <iomanip>
    
    class ByteReg {
      private:
        volatile uint8_t &reg;
      public:
        explicit ByteReg(volatile uint8_t &reg): reg(reg) { }
        ByteReg(const ByteReg&) = delete;
        ByteReg operator=(const ByteReg&) = delete;
        ~ByteReg() = default;
    
        operator uint8_t() { return reg; }
        bool test(int i) const
        {
          assert(i >= 0 && i < 8);
          return ((reg >> i) & 1) != 0;
        }
    };
    
    int main() 
    {
      volatile uint8_t hwReg = 0xaa; // 0x10101010
      ByteReg reg(hwReg);
      unsigned value = reg;
      std::cout << "reg: 0x" << std::hex << std::setw(2) << std::setfill('0')
        << value << '\n';
      for (int i = 0; i < 8; ++i) {
        std::cout << "bit " << i << ": "
          << (reg.test(i) ? "set" : "unset") << '\n';
      }
      return 0; 
    }
    

    输出:

    reg: 0xaa
    bit 0: unset
    bit 1: set
    bit 2: unset
    bit 3: set
    bit 4: unset
    bit 5: set
    bit 6: unset
    bit 7: set
    

    Live Demo on coliru

    但是,一个独立的函数 testBit()

    #include <cassert>
    #include <iostream>
    #include <iomanip>
    
    bool testBit(uint8_t reg, int i)
    {
      assert(i >= 0 && i < 8);
      return ((reg >> i) & 1) != 0;
    }
    
    int main() 
    {
      volatile uint8_t reg = 0xaa; // 0x10101010
      unsigned value = reg;
      std::cout << "reg: 0x" << std::hex << std::setw(2) << std::setfill('0')
        << value << '\n';
      for (int i = 0; i < 8; ++i) {
        std::cout << "bit " << i << ": "
          << (testBit(reg, i) ? "set" : "unset") << '\n';
      }
      return 0; 
    }
    

    Live Demo on coliru