C 预处理器计算最大 sizeof 结构

C preprocessor compute max sizeof structures

我有一个类似于这个简化示例的结构缓冲池:

struct astruct {
    int     c1;
    int     c2;
    union {
        atype1  u1;
        atype2  u2;
        atype3  u3;
    } u;
};

现在,我意识到其中一种联合类型 atype1 比其他联合类型大得多。我想将我的缓冲池分成 2 个独立的池,一个的内存块等于 sizeof(astruct),另一个的内存块足够大以容纳相同的结构,如果它不包含 u1 成员,上面的内容是

offsetof(astruct,u) + MAX(sizeof(atype2),sizeof(atype3))

如何让预处理器计算 MAX(sizeof,...),假设真的有十几种不同的联合类型?或者,是否有一种清晰易读的方式让预处理器在结构上制造不同的变体?

有办法。它有点笨拙,但它确实有效。您可能需要稍微调整一下。


首先创建头文件structdef.h:

struct STRUCT_NAME {
    int     c1;
    int     c2;
    union {
#if WANT_ATYPE & 1
        atype1  u1;
#endif
#if WANT_ATYPE & 2
        atype2  u2;
#endif
#if WANT_ATYPE & 4
        atype3  u3;
#endif
    } u;
};

#undef WANT_ATYPE
#undef STRUCT_NAME

现在创建一个文件structall.h:

#define WANT_ATYPE  (0x01 | 0x02 | 0x4)
#define STRUCT_NAME struct123
#include <structdef.h>

#define WANT_ATYPE  (0x02 | 0x4)
#define STRUCT_NAME struct23
#include <structdef.h>

#define WANT_ATYPE  (0x4)
#define STRUCT_NAME struct3
#include <structdef.h>

这将按照您想要的方式定义事物。大功告成。

但是,为了向您展示它的样子,这里是 cpp -E -P structall.h -I. 的输出:

struct struct123 {
    int c1;
    int c2;
    union {
        atype1 u1;
        atype2 u2;
        atype3 u3;
    } u;
};
struct struct23 {
    int c1;
    int c2;
    union {
        atype2 u2;
        atype3 u3;
    } u;
};
struct struct3 {
    int c1;
    int c2;
    union {
        atype3 u3;
    } u;
};

如果您不介意插入一堆反斜杠,则无需单独的包含文件即可完成此操作。但请阅读下面的警告,它也适用于 Craig Estey 较少使用反斜杠的解决方案。

#define INCLUDE(x) x
#define IGNORE(x)
#define STRUCT(NAME, VARIANT) \
struct NAME {                 \
  int     c1;                 \
  int     c2;                 \
  union {                     \
    VARIANT(char u1;)         \
    short u2;                 \
    char u3[100];             \
  } u;                        \
}

STRUCT(astruct, INCLUDE);
#define SHORTER sizeof(STRUCT(,IGNORE))

(live on coliru,略有不同)

但是注意:如果联合成员的对齐是由可能省略的元素而不是公共前缀的对齐决定的,那么省略元素可以减少填充在工会之前,你会得到错误的尺寸。参见 this snippet on coliru 其中 u3 被更改为 long double 结果计算为 SHORTER 的大小实际上小于并集的偏移量,这将导致不够space 正在分配给较短的池。