动态构造字节数组并返回长度的函数

时间:2015-03-31 06:16:09

标签: c++ encode

我需要在类

中创建编码器功能
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。

问题,

  1. 我应该如何分配内存?因为在调用此函数之前不知道

  2. 有没有办法映射类对象内存,基本上可以提供我想要的内容。

  3. 我知道这是一个非常基本的问题,但想要了解最佳和传统方法。

4 个答案:

答案 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;
}

这会将内存管理移动到流和调用方。如果您需要针对类型的特殊编码,请从istreamostream派生您的编解码器并使用它们。

使用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;
}