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
)。它做了以下工作:
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 achar*
而不是相反的方式…因此我的代码不遵守严格的别名规则…允许使用大量的东西,但并不总是按照您期望的方式工作。存储在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;
};
};