我需要在类
中创建编码器功能bool encodeMsg(unsigned char* buffer, unsigned short& len);
这个类有一些固定长度的成员和一些可变长度的向量(不同的结构)。 我必须根据这些成员变量的某些序列对Byte流进行编码。
这是一个可销售的版本,
class test
{
public:
test();
~test();
bool encodeMsg(unsigned char* buffer);
bool decodeMsg(const unsigned char* buffer, unsigned short len);
private:
unsigned char a; // 0x12
unsigned char b; // 0x34
unsigned char c; // 0x56
}
当我编码时,我想要的是我的缓冲区中的0x123456。
问题,
我应该如何分配内存?因为在调用此函数之前不知道
有没有办法映射类对象内存,基本上可以提供我想要的内容。
我知道这是一个非常基本的问题,但想要了解最佳和传统方法。
答案 0 :(得分:1)
我应该如何分配内存?因为在调用此函数之前不知道
鉴于您当前的代码,调用者应该分配内存:
unsigned char buffer[3];
unsigned short len = sizeof buffer;
my_test_object.encodeMsg(buffer, len);
有没有办法映射类对象内存,基本上给出了我想要的内容。
这很模糊。如果您使用(可能是编译器特定的)#pragma
或属性来确保字符值占用内存中的3个连续字节,并且只要您不添加任何虚拟函数您可以使用以下方法实现encodeMsg()
:
memcpy(buffer, (unsigned char*)this + offsetof(test, a), 3);
但是,有什么意义呢?充其量,我无法想象memcpy
比写出它的“好”方式更快:
buffer[0] = a;
buffer[1] = b;
buffer[2] = c;
如果你的意思更像是:
test* p = reinterpret_cast<test*>(buffer);
*p = *this;
那将有未定义的行为,并且可能会将最多sizeof(test)
个字节写入缓冲区,这很可能是4而不是3,这可能会导致某些客户端代码缓冲区溢出,删除已经设置的NUL终结者等。哈金和危险。
退后一步,如果你不得不提出这些问题,你应该担心采用良好的编程习惯 - 只有当你掌握了这种事情时,你应该担心吗?关于什么是最佳的。为了养成良好的习惯,您可能需要先查看boost序列化库并先熟悉它。
答案 1 :(得分:1)
C ++的方式是使用流。只需实现插入运算符<<
进行编码,就像这样
std::ostream& operator<<(std::ostream& os, const test& t)
{
os << t.a;
os << t.b;
os << t.c;
return os;
}
与用于解码的提取运算符>>
相同
std::istream& operator>>(std::istream& is, test& t)
{
is >> t.a;
is >> t.b;
is >> t.c;
return is;
}
这会将内存管理移动到流和调用方。如果您需要针对类型的特殊编码,请从istream
和ostream
派生您的编解码器并使用它们。
使用stringstream
这样的
test t;
std::ostringstream strm;
strm << t;
std::string result = strm.str();
auto size = result.length(); // size
auto array = result.data(); // the byte array
答案 2 :(得分:1)
如果您可以更改encodeMsg()
功能的界面,则可以将字节流存储在矢量中。
bool test::encodeMsg(std::vector<unsigned char>& buffer)
{
// if speed is important you can fill the buffer some other way
buffer.push_back(a);
buffer.push_back(b);
buffer.push_back(c);
return true;
}
如果encodeMsg()
无法失败(不需要返回bool),您可以创建并返回其中的向量:
std::vector<unsigned char> test::encodeMsg()
{
std::vector<unisgned char> buffer;
// if speed is important you can fill the buffer some other way
buffer.push_back(a);
buffer.push_back(b);
buffer.push_back(c);
return buffer;
}
答案 3 :(得分:0)
对于可以轻易复制std::is_trivially_copyable<test>::value == true
的类,编码和解码实际上是直接的(假设您已经为buffer
分配了内存:
bool encodeMsg(unsigned char* buffer, unsigned short& len) {
auto* ptr=reinterprete_cast<unsigned char*>(this);
len=sizeof(test);
memcpy(buffer, ptr, len);
return true;
}
bool decodeMsg(const unsigned char& buffer){
auto* ptr=reinterprete_cast<unsigned char*>(this);
memcpy(ptr, buffer, sizeof(test));
return true;
}
或更短
bool encodeMsg(unsigned char* buffer, unsigned short& len) {
len=sizeof(test);
memcpy(buffer, (unsigned char*)this, len);
return true;
}
bool decodeMsg(const unsigned char& buffer){
memcpy((unsigned char*)this, buffer, sizeof(test));
return true;
}
最有可能的是,由于填充,您将复制4个字节而不是3个字节。
就直接将字符串解释为字节数组而言 - 将指针从test *转换为unsigned char *并通过它访问对象是合法的,但不是相反。所以你能写的是:
unsigned char* buffer encodeMsg( unsigned short& len) {
len=sizeof(test);
return reinterprete_cast<unsigned char*>(this);
}
bool decodeMsg(const unsigned char& buffer){
auto* ptr=reinterprete_cast<unsigned char*>(this);
memcpy(ptr, buffer, sizeof(test));
return true;
}