用于确定多个结构的最大大小的 GCC Preproccesor 宏

J-D*_*zle 3 c embedded macros gcc

有没有办法生成一个宏来产生数据类型列表的最大大小?

目标

typedef struct {
    uint8_t x;
} A;

typedef struct {
    uint16_t x;
} B;

typedef struct {
    uint8_t x[10];
} C;

#define sizeof_max(A,B,C)   //compiles to '10'
Run Code Online (Sandbox Code Playgroud)

用例

通用数据段的不同值映射。

typedef union {
    uint8_t array[sizeof_max(A,B,C)];
    A iso_hugenum_a;
    B ext_a0;
    C ext_a1;  //and someday down the road 'D' may also get added
} DATA_SEG;
Run Code Online (Sandbox Code Playgroud)

这适用于设备实现基本协议 ISO_HUGENUM_A 的嵌入式应用程序。设备还必须支持此协议的扩展 EXT_A0、EXT_A1、EXT_B0。哎呀,在这种情况下,确实有可能 EXT_C0 出现在路上(糟糕)!

笔记

这里的主要目标是让顶级系统以可扩展和安全的方式了解数据段的大小。当您需要作为数组时,很容易只说“强制转换为数组”。但

  • 在系统级(谁没有给出关于协议的 eff)有读、写和检查(例如 crc)到这个数据段

  • 2 年后,“EXT_C0”可能会出现。我想给继承我代码的可怜人留下一些当 EXT_C0 增长数据段时不会破坏的东西

我希望有一个解决方案,但还没有找到。有任何想法吗?所有大小都将由预处理器生成,因此它似乎是宏的理想候选者。

-贾斯汀

Cli*_*ord 5

以下宏定义完全符合您的要求:

#define sizeof_max(s1,s2,s3) sizeof( union{s1 a; s2 b; s3 c; })
Run Code Online (Sandbox Code Playgroud)

对于您的示例,结构如下:

size_t s = sizeof_max( A,B,C ) ;
Run Code Online (Sandbox Code Playgroud)

结果s= 10。

当然DATA_SEGuint8_t*当您想作为字节数组访问时,您可以省略数组成员并简单地将对象地址强制转换为 a:

DATA_SEG x ;
uint8_t* array = (uint8_t*)&x ; 
Run Code Online (Sandbox Code Playgroud)

这将允许DATA_SEG在必要时添加更多结构而无需更改宏 - 更安全且更易于维护。


补充

另一种可能性是将专用解释与字节覆盖分开,因此:

typedef union 
{
    A iso_hugenum_a;
    B ext_a0;
    C ext_a1;  
    D added_someday ;
} DATA_SEG_U;

typedef union 
{
    uint8_t array[sizeof(DATA_SEG_U)];
    DATA_SEG_U data_seg ;
} DATA_SEG ;
Run Code Online (Sandbox Code Playgroud)