结构似乎是解析二进制blob数据(即文件或网络数据包)的有用方法。在blob中有可变大小的数组之前,这很好并且很花哨。例如:

struct nodeheader{
        int flags;
        int data_size;
        char data[];
};

这允许我找到最后一个数据字符:

nodeheader b;
cout << b.data[b.data_size-1];

问题是,我想拥有多个可变长度数组:

struct nodeheader{
    int friend_size;
    int data_size;
    char data[];
    char friend[];
};

我不是手动分配这些结构。我有一个这样的文件:

char file_data[1024];
nodeheader* node = &(file_data[10]);

因为我正在尝试解析二进制文件(更具体地说是一个类文件)。我用Java编写了一个实现(这是我的类分配),不是我在C ++中做个人版本,并且希望在不写100行代码的情况下逃脱。有什么想法吗?

谢谢, 斯蒂芬

有帮助吗?

解决方案

您不能拥有多个可变大小的数组。编译时编译器应该如何知道friend []所在的位置? friend的位置取决于data []的大小,并且在编译时数据的大小是未知的。

其他提示

这是一个非常危险的构造,我建议反对它。当结构为LAST元素时,只能在结构中包含一个可变长度数组,当你这样做时,你必须确保分配足够的内存,例如:

nodeheader *nh = (nodeheader *)malloc(sizeof(nodeheader) + max_data_size);

您要做的只是使用常规动态分配的数组:

struct nodeheader
{
  char *data;
  size_t data_size;
  char *friend;
  size_t friend_size;
};

nodeheader AllocNodeHeader(size_t data_size, size_t friend_size)
{
  nodeheader nh;
  nh.data = (char *)malloc(data_size);  // check for NULL return
  nh.data_size = data_size;
  nh.friend = (char *)malloc(friend_size);  // check for NULL return
  nh.friend_size = friend_size;

  return nh;
}

void FreeNodeHeader(nodeheader *nh)
{
  free(nh->data);
  nh->data = NULL;
  free(nh->friend);
  nh->friend = NULL;
}

你不能 - 至少不是以你正在尝试的简单方式。结构末尾的unsized数组基本上是结构末尾的偏移量,没有内置的方法来查找结尾。

所有字段在编译时都会转换为数字偏移量,因此需要在此时进行计算。

到目前为止,答案严重过于复杂化了一个简单的问题。 Mecki对于为什么不能按照你想要的方式完成它是正确的,但是你可以这样做:

struct nodeheader
{
    int friend_size;
    int data_size;
};

struct nodefile
{
    nodeheader *header;
    char *data;
    char *friend;
};

char file_data[1024];

// .. file in file_data ..

nodefile file;
file.header = (nodeheader *)&file_data[0];
file.data = (char *)&file.header[1];
file.friend = &file.data[file->header.data_size];

对于您正在做的事情,您需要格式化的编码器/解码器。解码器获取原始数据并填写您的结构(在您的情况下为数据的每个部分的副本分配空间),并且解码器写入原始二进制文件。

('使用std :: vector')

编辑:

在阅读反馈时,我想我应该扩大我的答案。您可以在结构中有效地拟合两个可变长度数组,如下所示,当file_data超出范围时,将自动释放存储空间:

struct nodeheader {
    std::vector<unsigned char> data;
    std::vector<unsigned char> friend_buf; // 'friend' is a keyword!
    // etc...
};

nodeheader file_data;

现在file_data.data.size()等为您提供了长度,并且&amp; file_data.data [0]为您提供了一个指向数据的原始指针。

你必须从文件中逐步填充文件数据 - 读取每个缓冲区的长度,在目标向量上调用resize(),然后读入数据。 (有一些方法可以更有效地执行此操作。在磁盘文件I / O的上下文中,我假设它没关系。)

顺便提一下,OP的技术即使对于他的'精细和花花公子'的情况也是不正确的,例如:最后只有一个VLA。

char file_data[1024];
nodeheader* node = &(file_data[10]);

无法保证file_data与nodeheader类型正确对齐。喜欢通过malloc()获取file_data - 它保证返回一个为任何类型对齐的指针 - 否则(更好)首先将缓冲区声明为正确的类型:

struct biggestnodeheader {
    int flags;
    int data_size;
    char data[ENOUGH_SPACE_FOR_LARGEST_HEADER_I_EVER_NEED];
};

biggestnodeheader file_data;
// etc...
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top