C++ 在C+中连接位+;

C++ 在C+中连接位+;,c++,bit-manipulation,C++,Bit Manipulation,我正在开发一个用于卷积编码器和位穿孔的软件 因此,在我的程序中,在每个循环中生成55位长度的数据。它存储在无符号长型变量的前55位。在每次迭代之后,我必须将这55位传输到一个无符号字符缓冲区(缓冲区相当大,比如500字节左右)。位必须连续存储在此缓冲区中。(即没有间隙)。是否有一些小技巧可以像这样轻松地连接起来?编辑:有人正确地向我指出,因为我通过uint64\u t*对字符缓冲区进行了别名,我违反了严格的别名规则,而且由于端点的不同,我也容易受到错误的攻击。尽管如此,如果您对平台有一定的保证,

我正在开发一个用于卷积编码器和位穿孔的软件


因此,在我的程序中,在每个循环中生成55位长度的数据。它存储在无符号长型变量的前55位。在每次迭代之后,我必须将这55位传输到一个无符号字符缓冲区(缓冲区相当大,比如500字节左右)。位必须连续存储在此缓冲区中。(即没有间隙)。是否有一些小技巧可以像这样轻松地连接起来?

编辑:有人正确地向我指出,因为我通过
uint64\u t*
对字符缓冲区进行了别名,我违反了严格的别名规则,而且由于端点的不同,我也容易受到错误的攻击。尽管如此,如果您对平台有一定的保证,这可能仍然有效。但可以通过使用64位元素的缓冲区而不是单个字节来解决此问题。

如果您想要一个不依赖任何外部库的基本算法,可以使用下面的代码段。请注意,位集仅用于显示结果并确保其正常工作

作为测试,我定义了一个55位的模式,由54个连续的1组成,后跟一个0。64位值(
x
)中的其余9位也是零。缓冲区是一个500字节的字符数组,我在
uint64\u t*
中使用了别名。该算法跟踪当前64位块(
currentBlock
)和该块中的当前位(
currentBit
)。它做了以下工作:

  • 移动位模式,使其从当前位位置开始
  • 或当前64位块的结果。这意味着位模式的第一部分连接到当前块的剩余部分。例如,在第二次迭代中,当第一块的前55位被填充时,剩余的9位将被占用
  • 更新
    currentBit
    变量
  • 检查
    currentBlock
    是否溢出,如果溢出,则移动到下一个块并连接55位模式的其余部分

    #include <iostream>
    #include <bitset> // only used for testing, not for the algorithm
    using namespace std;
    
    int main()
    {
        size_t nBits = 55;
    
        // 54 1's, followed by 10 0's
        uint64_t x = 0b1111111111111111111111111111111111111111111111111111110000000000;
    
        // 500 byte buffer:
        char buf8[500]{};
        uint64_t *buf = reinterpret_cast<uint64_t*>(&buf8[0]);
    
        // This would be better; use this if possible
        // uint64_t buf[100];
    
        int currentBit = 0;
        int currentBlock = 0;
    
        // concatenate the 55-bitpattern 10 times 
        for (int i = 0; i != 10; ++i)
        {
            buf[currentBlock] |= (x >> currentBit);
    
            currentBit += nBits;
            if (currentBit >= 64)
            {
                ++currentBlock;
                currentBit %= 64;
    
                buf[currentBlock] |= x << (nBits - currentBit);
            }
        }
    
        // TEST
        for (int i = 0; i != 5; ++i)
            cout << bitset<64>(buf[i]) << '\n';
    }
    

    请注意每55位标记一次0。

    我不久前编写了这个类,当时我需要处理位。这可能对你也有用。这是:

    #include <deque>
    #include <vector>
    #include <algorithm>
    
    class bitStream {
    public:
        bitStream() {}
    
        /// Copies the data from another bitStream into this one upon construction
        bitStream(const bitStream& bStream, bool reverse=false) {
            this->appendData(bStream, reverse);
        }
    
        /// Copies the data from a vector of booleans upon construction
        bitStream(const vector<bool>& vec, bool reverse=false) {
            this->appendData(vec, reverse);
        }
    
        /// Appends data to the stream from a uint64_t type. The lower-n bits will be appended, starting with the highest bit of those by default.
        void        appendData(uint64_t data, size_t n, bool reverse=false) {
            deque<bool> _buffer;
            n = (n>64)?64:n;
            for (int i=0; i<n; i++) {
                _oneBit tmp;
                tmp.data = data;
                _buffer.push_back(tmp.data);
                data >>= 0x1;
            }
            if (!reverse) std::reverse(_buffer.begin(), _buffer.end());
            for (const auto v: _buffer) _data.push_back(v);
        }
    
        /// Appends data to the stream from a C-style array of booleans
        void        appendData(bool* data, size_t n, bool reverse=false) {
            if (reverse) {
                for (int i=0; i<n; i++) this->appendBit(*(data+(n-i-1)));
            } else {
                for (int i=0; i<n; i++) this->appendBit(*(data+i));
            }
        }
    
        /// Appends data to the stream from a vector of booleans
        void        appendData(const vector<bool>& vec, bool reverse=false) {
            if (reverse) {
                for (auto i = vec.size()-1; vec.size() > i; --i) this->appendBit(vec.at(i));
            } else {
                for (const auto& v : vec) this->appendBit(v);
            }
        }
    
        /// Appends a single bit
        void        appendBit(bool bit) {
            _data.push_back(bit);
        }
    
        /// Appends the bits from another bitStream object to this one
        void        appendData(const bitStream& bStream, bool reverse=false) {
            if (!bStream.getSize()) return;
            if (reverse) {
                for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+(bStream.getSize()-i-1)));
            } else {
                for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+i));
            }
        }
    
        /// Returns a pointer to the begining of the data (read-only!)
        const bool* getData() const { return &_data.front(); }
    
        /// Reference to the bit at a specified position (assignable, but at lest n+1 elements must exist before calling!)
        bool& operator[] (size_t n) {
            if (n>_data.size()-1) throw runtime_error("Out of range!");
            return _data.at(n);
        }
    
        /// Fills your vector with the data chopped up into "sizeof(T)"-byte pieces.
        template <typename T>
        void        getDataAsVector(vector<T>& vec) {
            vec.clear();
            size_t oSize = sizeof(T)*8;
            T tmp = 0x0;
            for (int i=0; i<_data.size(); i++) {
                if (!(i%oSize) && i) {
                    vec.push_back(tmp);
                    tmp = 0x0;
                }
                tmp <<= 0x1;
                tmp |= _data[i];
            }
            vec.push_back(tmp);
        }
    
        /// Returns the number of bits that are stored
        size_t      getSize() const { return _data.size(); }
    
        /// Reverses the stored bits
        void        reverse() { std::reverse(_data.begin(), _data.end()); }
    private:
        deque<bool> _data;
        struct _oneBit {
            uint8_t data:1;
        };
    };
    
    #包括
    #包括
    #包括
    类位流{
    公众:
    比特流(){}
    ///在构造时将数据从另一个位流复制到此位流
    比特流(常量比特流和b流,布尔反向=false){
    此->追加数据(b流,反向);
    }
    ///在构造时从布尔向量复制数据
    比特流(const vector&vec,bool reverse=false){
    此->追加数据(vec,反向);
    }
    ///将数据从uint64_t类型追加到流中。将追加较低的n位,默认情况下从这些位中的最高位开始。
    无效追加数据(uint64数据,大小n,布尔反向=false){
    德克缓冲区;
    n=(n>64)?64:n;
    对于(int i=0;i>=0x1;
    }
    如果(!reverse)std::reverse(_buffer.begin(),_buffer.end());
    用于(常量自动v:_缓冲区)_数据。向后推(v);
    }
    ///将数据从C样式的布尔数组追加到流
    无效追加数据(布尔*数据,大小,布尔反向=false){
    如果(反向){
    对于(int i=0;iappendBit(*(数据+(n-i-1)));
    }否则{
    对于(int i=0;iappendBit(*(data+i));
    }
    }
    ///将数据从布尔向量追加到流
    无效追加数据(常量向量和向量,布尔反向=false){
    如果(反向){
    对于(auto i=vec.size()-1;vec.size()>i;--i)this->appendBit(vec.at(i));
    }否则{
    对于(const auto&v:vec)此->追加位(v);
    }
    }
    ///附加一个位
    无效位(布尔位){
    _数据。推回(位);
    }
    ///将另一个位流对象的位追加到此位流对象
    void appendData(常量比特流和b流,bool reverse=false){
    如果(!bStream.getSize())返回;
    如果(反向){
    对于(inti=0;iappendBit(*(bStream.getData()+(bStream.getSize()-i-1));
    }否则{
    对于(int i=0;iappendBit(*(bStream.getData()+i));
    }
    }
    ///返回指向数据开头的指针(只读!)
    const bool*getData()const{return&_data.front();}
    ///在指定位置对位的引用(可赋值,但在调用之前至少必须存在n+1个元素!)
    bool和操作员[](尺寸){
    如果(n>_data.size()-1)抛出运行时_错误(“超出范围!”);
    返回(n)处的数据;
    }
    ///用切碎为“sizeof(T)”字节片段的数据填充向量。
    模板
    void getDataAsVector(vector和vec){
    向量清除();
    尺寸=尺寸(t)*8;
    T tmp=0x0;
    
    对于(int i=0;我能更改您正在使用的数据类型吗?您能使用吗?我不知道有什么简单的技巧。您必须使用某种位打包数据结构,或者组装位oldskool样式。@adam10603如果有助于解决此问题,我可以。@NathanOliver位集的问题是它的大小固定,不容易转换回long字节数组,除非我遗漏了什么。
    reinterpret\u cast
    =不好。适用于您的编译器,甚至可能适用于他的编译器。但不能保证。@NeilKirk如果我错了,请纠正我,但我相信标准中规定允许将
    char*
    强制转换为任何其他指针类型。编辑:我对别名混淆了h a
    char*
    而不是相反的方式…因此我的代码不遵守严格的别名规则…允许使用大量的东西,但并不总是按照您期望的方式工作。存储在
    buf8
    中的结果在小端和大端机器之间会有所不同。如果我们要谈论大/小端,位操作就不会得到根据定义,瑞奇……你可以
    #include <deque>
    #include <vector>
    #include <algorithm>
    
    class bitStream {
    public:
        bitStream() {}
    
        /// Copies the data from another bitStream into this one upon construction
        bitStream(const bitStream& bStream, bool reverse=false) {
            this->appendData(bStream, reverse);
        }
    
        /// Copies the data from a vector of booleans upon construction
        bitStream(const vector<bool>& vec, bool reverse=false) {
            this->appendData(vec, reverse);
        }
    
        /// Appends data to the stream from a uint64_t type. The lower-n bits will be appended, starting with the highest bit of those by default.
        void        appendData(uint64_t data, size_t n, bool reverse=false) {
            deque<bool> _buffer;
            n = (n>64)?64:n;
            for (int i=0; i<n; i++) {
                _oneBit tmp;
                tmp.data = data;
                _buffer.push_back(tmp.data);
                data >>= 0x1;
            }
            if (!reverse) std::reverse(_buffer.begin(), _buffer.end());
            for (const auto v: _buffer) _data.push_back(v);
        }
    
        /// Appends data to the stream from a C-style array of booleans
        void        appendData(bool* data, size_t n, bool reverse=false) {
            if (reverse) {
                for (int i=0; i<n; i++) this->appendBit(*(data+(n-i-1)));
            } else {
                for (int i=0; i<n; i++) this->appendBit(*(data+i));
            }
        }
    
        /// Appends data to the stream from a vector of booleans
        void        appendData(const vector<bool>& vec, bool reverse=false) {
            if (reverse) {
                for (auto i = vec.size()-1; vec.size() > i; --i) this->appendBit(vec.at(i));
            } else {
                for (const auto& v : vec) this->appendBit(v);
            }
        }
    
        /// Appends a single bit
        void        appendBit(bool bit) {
            _data.push_back(bit);
        }
    
        /// Appends the bits from another bitStream object to this one
        void        appendData(const bitStream& bStream, bool reverse=false) {
            if (!bStream.getSize()) return;
            if (reverse) {
                for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+(bStream.getSize()-i-1)));
            } else {
                for (int i=0; i<bStream.getSize(); i++) this->appendBit(*(bStream.getData()+i));
            }
        }
    
        /// Returns a pointer to the begining of the data (read-only!)
        const bool* getData() const { return &_data.front(); }
    
        /// Reference to the bit at a specified position (assignable, but at lest n+1 elements must exist before calling!)
        bool& operator[] (size_t n) {
            if (n>_data.size()-1) throw runtime_error("Out of range!");
            return _data.at(n);
        }
    
        /// Fills your vector with the data chopped up into "sizeof(T)"-byte pieces.
        template <typename T>
        void        getDataAsVector(vector<T>& vec) {
            vec.clear();
            size_t oSize = sizeof(T)*8;
            T tmp = 0x0;
            for (int i=0; i<_data.size(); i++) {
                if (!(i%oSize) && i) {
                    vec.push_back(tmp);
                    tmp = 0x0;
                }
                tmp <<= 0x1;
                tmp |= _data[i];
            }
            vec.push_back(tmp);
        }
    
        /// Returns the number of bits that are stored
        size_t      getSize() const { return _data.size(); }
    
        /// Reverses the stored bits
        void        reverse() { std::reverse(_data.begin(), _data.end()); }
    private:
        deque<bool> _data;
        struct _oneBit {
            uint8_t data:1;
        };
    };