【问题标题】:Declare two different struct sizes [closed]声明两种不同的结构大小
【发布时间】:2016-03-23 18:26:33
【问题描述】:

这是在微控制器平台上,因此 RAM 的使用很重要。

我有一个不错的小库,可用于循环缓冲区。对于循环缓冲区,我声明了一个 struct typedef:

typedef struct buffer {
    uint8_t data[BUFFER_LENGTH];
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
} Buffer;

通常,每个应用程序只需要其中一个,因此将 BUFFER_LENGTH 定义为特定值并不是什么大不了的事,但我有一个应用程序需要其中两个...其中一个长度相对较短(32字节)和相对较长的长度(256 字节)之一。

是否有一种不涉及malloc() 的简单技术可以让我声明两个不同长度的变量?

目前我唯一想到的就是把struct中的数据做成指针,在声明缓冲区的时候声明数组,把缓冲区长度加到Buffer typedef中:

typedef struct buffer {
    uint8_t dataPtr*;
    uint16_t length;
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
} Buffer;

uint8_t dataBuf1[256]
uint8_t dataBuf2[32]

Buffer buf1, buf2;

buf1.dataPtr = dataBuf1;
buf1.length = 256;

buf2.dataPtr = dataBuf2;
buf2.length = 32;

这可行,但有更好的解决方案吗?

【问题讨论】:

  • 声明结构不需要额外的空间,在你实例化它之前它不会占用空间。既然你都需要它们,只需声明它们。
  • @KevinDTimm 感谢您查看此内容。如果我声明Buffer buf1Buffer buf2,那么我的编译器将为每个分配完整的BUFFER_LENGTH。这在功能上会起作用,但会使用比我感兴趣的更多的 RAM。
  • 是的,我看到了这一点(尤其是在查看 @WeatherVan 的答案之后)。我对问题的解释不正确
  • @KevinDTimm 我可以添加措辞来澄清解释吗?
  • 不,问题很清楚(我只是懒惰阅读)

标签: c struct typedef


【解决方案1】:

你可以像这样定义两个结构体:

#define LARGE_BUFFER_LENGTH   256
#define SMALL_BUFFER_LENGTH   32

typedef struct buffer {
    uint16_t buffer_size;
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
    uint8_t data[LARGE_BUFFER_LENGTH];
} Large_Buffer;

typedef struct buffer {
    uint16_t buffer_size;
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
    uint8_t data[SMALL_BUFFER_LENGTH];
} Small_Buffer;

data 成员移至末尾,并添加buffer_size 成员。您应该能够共享处理函数,方法是将指针转换为较小的类型以使其为编译器所接受。 C 不关心您是否明显溢出数组,buffer_size 字段将处理实现差异。您可以在之前使用BUFFER_LENGTH 的任何地方使用buffer_size(当然是初始化)。

【讨论】:

  • 并且,如果 OP 非常担心空间(并且变量只是 SMALL_ 和 LARGE_ 2 个值之一),则 buffer_size 可能只是 char
  • @KevinDTimm 但 OP 不想使用 malloc
  • 或者,更好的是,为了节省更多空间,与元素 data_small[SMALL_BUFFER_LENGTH]data_large[LARGE_BUFFER_LENGTH] 合并
  • 不需要malloc,将buffer_size设置为使用的大小并根据该值执行所有操作。
  • @KevinDTimm 在小情况下联合会使用不必要的内存。
【解决方案2】:

如果您不想要动态分配,您可以使用如下定义:

typedef struct buffer {
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
    int length;
    uint8_t data[];
} Buffer;

然后是两个兼容的定义类型:

typedef struct buffer1 {
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
    int length;
    uint8_t data[LENGHT1];
} Buffer1_t;

和:

typedef struct buffer2 {
    uint16_t newest_index;
    uint16_t oldest_index;
    BufferStatus status;
    int length; // may be useful...
    uint8_t data[LENGHT2];
} Buffer2_t;

那你就可以用指针来玩了:

Buffer *allocate_buffer(int type) {
    if (type==1) {
      return (Buffer *)malloc(sizeof(Buffer1_t));
    } else ...
}    

如果您不想要动态分配,您可以使用静态预分配的此类结构。

【讨论】:

  • “兼容的定义类型”不兼容(在 C 中,只有完全相同的结构才 兼容)。您还需要使用不同的结构标签(不是所有的struct buffer)。
  • 没有适用于兼容类型(std 6.2.7)和灵活数组成员(6.7.2.1/18)的规则。我误解了吗?
  • 结构的兼容性要求包括“如果一个用标签声明,另一个应该用相同的标签声明。”。 (即使拥有相同的成员列表也是不够的)。顺便说一句,我认为你的想法确实有效,只是在评论“兼容”这个词。
  • 你说得对,示例 6.7.2.1/20 清楚地说明了这一点。但如果它真的发生,我会感到惊讶......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多