How to make a dynamic structure in C



例如,如果我有这样的结构:

typedef struct __attribute__ ((packed))
{
uint16_t    ObjectPropertyCode;
uint16_t    DataType;
uint8_t     GetSet;
union
{
uint8_t     DefaultValue_u8 ;
uint16_t    DefaultValue_u16 ;
uint32_t    DefaultValue_u32 ;
}DefValue  ;
uint32_t    GroupCode;
uint8_t     FormFlag;
}
MTP_ObjectPropDescTypeDef;

根据我的DataType,我只需要在DefValue中有一个元素。例如,如果我的DataType是uint16,那么我将发送这样的结构:

typedef struct __attribute__ ((packed))
{
uint16_t    ObjectPropertyCode;
uint16_t    DataType;
uint8_t     GetSet;
uint16_t    DefaultValue_u16 ;
uint32_t    GroupCode;
uint8_t     FormFlag;
}
MTP_ObjectPropDescTypeDef;

除非您将数据布局分解为多个部分,或者更改数据布局,使可变大小类型位于末尾,否则您的建议是不可能实现的(好吧,无论如何都是合理的(。

解决了这个问题,我们就可以进入不合理的部分。您可以(ab(使用预处理器在一定程度上有效地实现这一点。(例如(:

#define JOIN3(a, b, c) a##b##c
#define MYSTRUCT(n) 
struct __attribute__ ((packed)) { 
uint16_t ObjectPropertyCode; 
uint16_t DataType; 
uint8_t GetSet; 
JOIN3(uint, n, _t) DefaultValue; 
uint32_t GroupCode; 
uint8_t FormFlag; 
}
// ...
{
MYSTRUCT(8) obj; // uint8_t DefaultValue
printf("%lun", sizeof(obj)); // 11
MYSTRUCT(16) obj2; // uint16_t DefaultValue
printf("%lun", sizeof(obj2)); // 12
MYSTRUCT(32) obj3; // uint32_t DefaultValue
printf("%lun", sizeof(obj3)); // 14
}

但是,它实现了类似的效果,只需要从三个不同的结构开始。在适用的情况下,考虑使用替代方法,即将结构分解为多个部分、具有不同的部分或仅使用纯缓冲区。

考虑下面的方法,该方法将根据提供的数据构建缓冲区。例如:

void build_output_buffer(const MTP_ObjectPropDescTypeDef *def, uint8_t *out)
{
size_t header_size = offsetof(MTP_ObjectPropDescTypeDef, DefValue);
memcpy(out, def, header_size);
out += header_size;
switch (def->DataType) {
// Copy the appropriate value, e.g.:
case DataType_U32: { // For demonstration's sake
memcpy(out, &def->DefValue, 4);
out += 4;
} break;
}
size_t footer_offset = offsetof(MTP_ObjectPropDescTypeDef, GroupCode);
size_t footer_size = sizeof(MTP_ObjectPropDescTypeDef) - footer_offset;
memcpy(out, (uint8_t*)def + footer_offset, footer_size);
}

并确保传入的缓冲区足够大,可以容纳所有数据。或者在函数内部分配并返回。或者跳过缓冲区,用类似的逻辑发送数据。

相关内容

  • 没有找到相关文章

最新更新