0

您将如何很好地表示字节数组及其大小?我想存储(在主内存或文件中)原始字节数组(无符号字符),其中前 2/4 个字节将代表其大小。但是对这样的数组的操作看起来并不好:

void func(unsigned char *bytearray)
{
  int size;
  memcpy(&size, bytearray, sizeof(int));
  //rest of operation when we know bytearray size
}

我怎样才能避免这种情况?我想一个简单的结构:

struct bytearray
{
  int size;
  unsigned char *data;
};

bytearray *b = reinterpret_cast<bytearray*>(new unsigned char[10]);
b->data = reinterpret_cast<unsigned char*>(&(b->size) + 1);

而且我可以访问字节数组的大小和数据部分。但它看起来仍然很丑。你能推荐另一种方法吗?

4

3 回答 3

5

除非您有一些压倒性的理由不这样做,否则只需做惯用的事情并使用 std::vector<unsigned char>。

于 2013-04-08T22:27:18.833 回答
2

您实际上是在重新发明"Pascal string"。然而

 b->data = reinterpret_cast<unsigned char*>(&(b->size) + 1);

根本不起作用,因为指针指向自身,并且指针将被覆盖。

您应该能够为结构的最后一个元素使用未指定大小的数组:

struct bytearray
{
  int size;
  unsigned char data[];
};

bytearray *b = reinterpret_cast<bytearray*>(::operator new(sizeof (bytearray) + 10));
b->size = 10;

//...

::operator delete(b);

与 不同std::vector的是,这实际上将大小和数据存储在一起,因此您可以例如在一次操作中将其写入文件。并且内存局部性更好。

尽管如此,std::vector已经过测试并且为您实现了许多有用的算法的事实使它非常有吸引力。

于 2013-04-08T22:23:45.640 回答
2

我会用它std::vector<unsigned char>来管理内存,并编写一个转换函数来iovec在你需要这样的东西时为你创建一些类似的结构。

iovec make_iovec (std::vector<unsigned char> &v) {
    iovec iv = { &v[0], v.size() };
    return iv;
}

使用iovec,如果您需要在单个系统调用中同时写入长度和数据,您可以使用该writev调用来完成它。

ssize_t write_vector(int fd, std::vector<unsigned char> &v) {
    uint32_t len = htonl(v.size());
    iovec iv[2] = { { &len, sizeof(uint32_t) }, make_iovec(v) };
    return writev(fd, iv, 2);
}
于 2013-04-08T22:34:58.787 回答