简体   繁体   English

使用C联盟“保留”数据空间 - 合理吗?

[英]Using C unions to “reserve” space in data - reasonable?

Sorry if the title is a bit skew, I couldn't think of a concise explanation of what I'm on about! 对不起,如果标题有点歪斜,我想不出有关我的内容的简明解释!

Anyway, we have an embedded system that stores its settings data in a small SPI EEPROM/Flash chip. 无论如何,我们有一个嵌入式系统,可将其设置数据存储在一个小的SPI EEPROM / Flash芯片中。 In a very basic form it's a struct containing the settings data, a simplified version might look like: 在一个非常基本的形式中,它是一个包含设置数据的结构, 简化版本可能如下所示:

struct settings_data
{
   struct factory_data
   { // Data set at the factory
      uint32 serial_number;
      uint32 calibration;
   };
   struct user_data
   { // User-configured data follows:
      uint8  user_data_1;
      uint8  user_data_2;
      char[10]  somestring;
      // etc...
   };
 }

All fine and dandy until we need to stick an extra value into _factory_data_, at which point everything after it moves. 一切都很好,直到我们需要在_factory_data_中加上一个额外的值,此时它会移动一切。

Now, there are many ways to handle this, but this question is not about finding a different method, it's about whether this idea is reasonable to pad out the data structures so that they don't move when you add things: 现在,有很多方法可以解决这个问题,但是这个问题并不是要找到一个不同的方法,而是关于这个想法是否合理来填充数据结构以便在添加内容时它们不会移动:

struct settings_data
{
   union factory_union
   {
      uint8 padding[100]; // Effectively reserve 100 bytes space
      struct factory_data
      { // Data set at the factory
         uint32 serial_number;
         uint32 calibration;
      };
   };
   union user_union
   {
      uint8 padding[100]; // Effectively reserve 100 bytes space
      struct user_data
      { // User-configured data follows:
         uint8  user_data_1;
         uint8  user_data_2;
         char[10]  somestring;
         // etc...
      };
   };
 }

If I understand unions correctly, this will reserve 100 bytes storage in the settings_data structure, and any new members we add to the "real" data struct inside the union will not cause the union to grow unless we exceed 100 bytes. 如果我正确理解了联合,这将在settings_data结构中保留100个字节的存储空间,并且我们添加到联合内部的“真实”数据结构中的任何新成员都不会导致联合增长,除非我们超过100个字节。

The question is is this a reasonable way to achieve this, given that we have relatively limited resources? 问题是,鉴于我们资源相对有限,这是实现这一目标的合理方法吗?

It is reasonable, but it is possible for the size of the union to change when your structure changes even if the structure is still smaller than the padding element. 这是合理的,但是当结构发生变化时,即使结构仍小于填充元素,联合的大小也可能会发生变化。

As it is in your question, the union is likely 100 bytes. 正如你的问题,联盟可能是100个字节。 Suppose you add a double to the structure, which (we assume) requires eight-byte alignment. 假设您在结构中添加了一个double ,我们假设它需要8字节对齐。 Then the compiler makes the union 104 bytes, so that its size will be a multiple of eight (which is necessary so that arrays of the union would maintain the required alignment). 然后编译器使联合104字节,使其大小为8的倍数(这是必要的,以便联合的数组将保持所需的对齐)。

You can avoid this by making the padding a multiple of the alignment requirement of all types you might add in the future. 您可以通过使填充为将来可能添加的所有类型的对齐要求的倍数来避免这种情况。

If I understand unions correctly, this will reserve 100 bytes storage in the settings_data structure, and any new members we add to the "real" data struct inside the union will not cause the union to grow unless we exceed 100 bytes. 如果我正确理解了联合,这将在settings_data结构中保留100个字节的存储空间,并且我们添加到联合内部的“真实”数据结构中的任何新成员都不会导致联合增长,除非我们超过100个字节。

Correct. 正确。 The size of a union is determined by the largest part. 联合的大小由最大的部分决定。 I don't see any problems with your solution. 我认为您的解决方案没有任何问题。 Provided your target platform does not change. 如果您的目标平台没有变化。 However, if the target platform changes, union and struct may "behave" differently due to padding and alignment done by compiler/linker. 但是,如果目标平台发生更改,则由于编译器/链接器执行填充和对齐,union和struct可能会“表现”不同。 Little endian and big endian, on the other hand, would not matter in this case, as long as you only use the "real" part of the union. 另一方面,小端和大端,在这种情况下无关紧要,只要你只使用联合的“真实”部分。

Also you may consider padding done by compiler/linker to achieve a specific alignment. 您也可以考虑编译器/链接器完成填充以实现特定的对齐。 That is, your "real" part of the union may get bigger than expected. 也就是说,你工会的“真实”部分可能会比​​预期更大。 For example, to have 32-bit values aligned some 0-3 octets padding may be added automatically before such an entry in your struct. 例如,要使32位值对齐,可以在结构中的这样一个条目之前自动添加一些0-3个八位字节的填充。 This depends on the target platform and the compiler/linker. 这取决于目标平台和编译器/链接器。 Please refer to the manual of your compiler/linker. 请参阅编译器/链接器的手册。

Hope this helps. 希望这可以帮助。 Cheers, Michael 干杯,迈克尔

Yes, using the union for padding should work. 是的,使用union进行填充应该可行。

And I can't resist giving this little bit of advice. 我无法抗拒给出这一点建议。 Put a version number in each struct. 在每个结构中放置一个版本号。 Then new versions of the software will be able to identify old versions of the structs. 然后,该软件的新版本将能够识别结构的旧版本。

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

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