简体   繁体   English

为什么要在结构体中保留memory?

[英]Why reserve memory in the structure?

I often see structures in the code, at the end of which there is a memory reserve.我经常在代码中看到结构体,最后有一个memory预留。


struct STAT_10K4
{
     int32_t npos; // position number
     ...
     float Plts;
             Pxts;
     float Plto [NUM];
     uint32_t reserv [(NUM * 3)% 2 + 1];
};
  1. Why do they do this?他们为什么这样做呢?
  2. Why are some of the reserve values dependent on constants?为什么某些保留值取决于常数?
  3. What can happen if you do not make such reserves?如果您不进行此类储备,会发生什么情况? Or make a mistake in their size?或者尺寸有误?

This is a form of manual padding of a class to make its size a multiple of some number.这是 class 的一种手动填充形式,以使其大小成为某个数字的倍数。 In your case:在你的情况下:

uint32_t reserv [(NUM * 3)% 2 + 1];

NUM * 3 % 2 is actually nonsensical, as it would be equivalent to NUM % 2 (not considering overflow). NUM * 3 % 2实际上是无意义的,因为它等同于NUM % 2 (不考虑溢出)。 So if the array size is odd, we pad the struct with one additional uint32_t , on top of + 1 additional ones.因此,如果数组大小为奇数,我们会在+ 1个额外的uint32_t之上用一个额外的 uint32_t 填充struct This padding means that STAT_10K4 's size is always a multiple of 8 bytes.此填充意味着STAT_10K4的大小始终是 8 字节的倍数。

You will have to consult the documentation of your software to see why exactly this is done.您将不得不查阅您的软件的文档以了解为什么要这样做。 Perhaps padding this struct with up to 8 bytes makes some algorithm easier to implement.也许用最多 8 个字节填充此结构会使某些算法更容易实现。 Or maybe it has some perceived performance benefit.或者它可能具有一些可感知的性能优势。 But this is pure speculation.但这纯粹是猜测。

Typically, the compiler will pad your struct s to 64-bit boundaries if you use any 64-bit types, so you don't need to do this manually.通常,如果您使用任何 64 位类型,编译器会将您的struct填充到 64 位边界,因此您无需手动执行此操作。


Note: This answer is specific to mainstream compilers and x86. Obviously this does not apply to compiling for TI-calculators with 20-bit char & co.注意:此答案特定于主流编译器和 x86。显然这不适用于使用 20 位char & co 编译 TI 计算器。

This would typically be to support variable-length records.这通常是为了支持可变长度记录。 A couple of ways this could be used will be:可以使用的几种方法是:

1 If the maximum number of records is known then a simple structure definition can accomodate all cases. 1 如果已知最大记录数,那么一个简单的结构定义就可以适应所有情况。

2 In many protocols there is a "header-data" idiom. 2 在许多协议中有一个“头数据”惯用语。 The header will be a fixed size but the data variable. header 将是固定大小但数据可变。 The data will be received as a "blob".数据将作为“blob”接收。 Thus the structure of the header can be declared and accessed by a pointer to the blob, and the data will follow on from that.因此,可以通过指向 blob 的指针声明和访问 header 的结构,数据将从那里继续。 For example:例如:

typedef struct
{
    uint32_t messageId;
    uint32_t dataType;
    uint32_t dataLenBytes;
    uint8_t data[MAX_PAYLOAD];
}
tsMessageFormat;

The data is received in a blob, so a void* ptr, size_t len .数据以 blob 形式接收,因此是一个void* ptr, size_t len

The buffer pointer is then cast so the message can be read as follows:然后转换缓冲区指针,以便可以按如下方式读取消息:

tsMessageFormat* pMessage = (psMessageFormat*) ptr;
for (int i = 0;  i < pMessage->dataLenBytes;  i++)
{
    //do something with pMessage->data[i];
}

In some languages the "data" could be specified as being an empty record, but C++ does not allow this.在某些语言中,“数据”可以指定为空记录,但 C++ 不允许这样做。 Sometimes you will see the "data" omitted and you have to perform pointer arithmetic to access the data.有时您会看到省略了“数据”,您必须执行指针运算才能访问数据。

The alternative to this would be to use a builder pattern and/or streams.替代方案是使用构建器模式和/或流。

Windows uses this pattern a lot; Windows 经常使用这种模式; many structures have a cbSize field which allows additional data to be conveyed beyond the structure.许多结构都有一个cbSize字段,它允许在结构之外传送额外的数据。 The structure accomodates most cases, but having cbSize allows additional data to be provided if necessary.该结构适用于大多数情况,但具有 cbSize 允许在必要时提供额外的数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM