用类修改字节中的位

时间:2015-02-01 18:21:07

标签: c++ bitset

我想直接修改一个字节中的位。

在GCC中,您可以按照以下方式执行此操作:

struct virtualByte {
    unsigned char b0 : 1;
    unsigned char b1 : 1;
    unsigned char b2 : 1;
    unsigned char b3 : 1;
    unsigned char b4 : 1;
    unsigned char b5 : 1;
    unsigned char b6 : 1;
    unsigned char b7 : 1;
} __attribute__((__packed__));

#define sbit(_byte, _pos) (((volatile struct virtualByte *)&_byte)->b ## _pos)

用法:

unsigned char myByte = 0x00;

#define firstBit sbit(myByte, 0)

firstBit = 1; // Implicit myByte |= 0x01;

为了让事情更整洁我想要上课为我做这件事。我提出了以下概念:

unsigned char myByteRef = 0x00;

Byte myByte(&myByteRef);

myByte[0] = 1; // Implicit myByteRef |= 0x01;

fprintf(stderr, "%2.2X\n", myByteRef);

但是这不起作用,因为在c ++中你不能返回对单个位的引用。重载构造函数也不起作用。

是否有可能实施此类行为?赋值运算符应直接修改其基础字节(而不是一组字节)。

2 个答案:

答案 0 :(得分:2)

您想使用std::bitset

std::bitset<12> someBits; // 12 bits
someBits[0] = true; // set 1st bit
std::cout << someBits.count() << '\n'; // prints 1

std::bitset<12>::reference bit5 = someBits[5];
bit5 = true;
std::cout << someBits.count() << '\n'; // prints 2

您可以使用index operator以您想要的方式返回对某位的引用。请注意,此引用不是bool&,而是std::bitset::reference

答案 1 :(得分:0)

终于找到了解决方案,非常感谢@doc!

我的解决方案:

class Bit {
    private:
        volatile uint8_t    *byte;
        uint8_t             bitPos;

    public:
        Bit(void)
        {
        }

        void init(volatile uint8_t *const byte, uint8_t const bitPos)
        {
            this->byte      = byte;
            this->bitPos    = (bitPos > 7u ? 7u : bitPos);
        }

        void setValue(bool const bitValue)
        {
            if (!this->byte) return;

            if (bitValue) {
                *this->byte |=  (1u << this->bitPos);
            } else {
                *this->byte &= ~(1u << this->bitPos);
            }
        }
};

class BitReference {
    private:
        Bit         &ref;

    public:
        BitReference(Bit &ref) : ref(ref)
        {
        }

        void operator=(bool const bitValue)
        {
            this->ref.setValue(bitValue);
        }
};

class Byte {
    private:
        Bit         bits[8];

    public:
        Byte(volatile uint8_t *const byte)
        {
            for (unsigned i = 0; i < 8; ++i) {
                this->bits[i].init(byte, i);
            }
        }

        /* This did the trick :)! */
        BitReference operator[](size_t index)
        {
            if (index > 7) index = 7;

            return BitReference(this->bits[index]);
        }
};

用法:

uint8_t myPort = 0x00;

int main(int const argc, const char **const argv)
{
    Byte abc(&myPort);

    abc[0] = 1;
    abc[1] = 1;
    abc[2] = 1;
    abc[3] = 1;

    fprintf(stderr, "%2.2X\n", myPort);

    return 0;
}