C++ 取消对结构中可变大小数组的引用

C++ 取消对结构中可变大小数组的引用,c++,struct,C++,Struct,结构似乎是解析二进制数据块(即文件或网络数据包)的有用方法。在blob中有可变大小的数组之前,这是很好的。例如: struct nodeheader{ int flags; int data_size; char data[]; }; 这允许我查找最后一个数据字符: nodeheader b; cout << b.data[b.data_size-1]; 我不是手动分配这些结构。我有一个这样的文件: char file_data[1

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

struct nodeheader{
        int flags;
        int data_size;
        char data[];
};
这允许我查找最后一个数据字符:

nodeheader b;
cout << b.data[b.data_size-1];
我不是手动分配这些结构。我有一个这样的文件:

char file_data[1024];
nodeheader* node = &(file_data[10]);
当我试图解析二进制文件(更具体地说是类文件)时。我已经在java中编写了一个实现(这是我的类任务),不,我在C++中做个人版本,希望不用编写100行代码就能逃脱。有什么想法吗

谢谢,
Stefan

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

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

您不能-至少不能以您正在尝试的简单方式。结构末端的未调整大小的数组基本上是结构末端的偏移量,没有内置方法来查找末端


所有字段都在编译时转换为数值偏移量,因此它们需要在编译时可计算。

您不能这样做,至少不能以您尝试的简单方式进行计算。结构末端的未调整大小的数组基本上是结构末端的偏移量,没有内置方法来查找末端


所有字段都在编译时转换为数值偏移量,因此它们需要在编译时可计算。

这是一种非常危险的构造,我建议不要这样做。只有当结构中的可变长度数组是最后一个元素时,才能在其中包含该数组,并且在执行此操作时,必须确保分配足够的内存,例如:

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

这是一个非常危险的构造,我建议不要这样做。只有当结构中的可变长度数组是最后一个元素时,才能在其中包含该数组,并且在执行此操作时,必须确保分配足够的内存,例如:

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;
}
(是“使用std::vector”)

编辑:

在阅读反馈时,我想我应该扩展我的答案。您可以按如下方式在结构中有效地安装两个可变长度数组,并且当文件\ U数据超出范围时,将自动为您释放存储:

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

nodeheader file_data;
无法保证文件\u数据与节点头类型正确对齐。首选通过malloc()获取文件_数据-这保证返回与任何类型对齐的指针-或者(更好)首先声明缓冲区的类型正确:

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

biggestnodeheader file_data;
// etc...
(是“使用std::vector”)

编辑:

在阅读反馈时,我想我应该扩展我的答案。您可以按如下方式在结构中有效地安装两个可变长度数组,并且当文件\ U数据超出范围时,将自动为您释放存储:

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

nodeheader file_data;
无法保证文件\u数据与节点头类型正确对齐。首选通过malloc()获取文件_数据-这保证返回与任何类型对齐的指针-或者(更好)首先声明缓冲区的类型正确:

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

biggestnodeheader file_data;
// etc...

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

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

到目前为止,答案严重地把一个简单的问题复杂化了。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];

到目前为止,答案严重地将一个简单的问题复杂化了。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];

这是一个很好的观点,我理解它,我想我的问题仍然是:有没有一个好的方法来做到这一点?那里有大量的二进制文件,编写数百行代码只是头的一个实现是一件痛苦的事情。实际上,由于结构有填充,如果你告诉编译器不要使用填充,你只能用它来解析压缩的二进制数据。在GCC中,您可以使用_属性_((打包));只需在谷歌上搜索这个。关于如何做到这一点,请提出一个新的问题(这样有类似问题的用户可以找到答案),我很高兴为您提供现成的代码。只要提供一些示例数据,以及解析后的外观就可以了。这是一个很好的观点,我理解它,我想我的问题仍然是:有没有一种好的方法可以做到这一点?那里有大量的二进制文件,编写数百行代码只是头的一个实现是一件痛苦的事情。实际上,由于结构有填充,如果你告诉编译器不要使用填充,你只能用它来解析压缩的二进制数据。在GCC中,您可以使用_属性_((打包));只需在谷歌上搜索这个。关于如何做到这一点,请提出一个新的问题(这样有类似问题的用户可以找到答案),我很高兴为您提供现成的代码。只需提供一些示例数据以及解析后的外观。我同意“使用
std::vector
”通常是有关二进制数据处理问题的正确答案,但您能否详细说明在特定情况下,它将如何使提问者的生活更轻松?我同意“使用
std::vector
”通常是