我有一个结构缓冲池,看起来像这个简化的例子:
struct astruct {
int c1;
int c2;
union {
atype1 u1;
atype2 u2;
atype3 u3;
} u;
};
现在,我意识到其中一种联合类型,比如atype1
,比其他类型要大得多。我想将我的缓冲池分成两个独立的池,一个内存块等于sizeof(astruct)
,另一个内存块足够大,如果它不包含u1
成员,则保持相同的结构,上面将是
offsetof(astruct,u) + MAX(sizeof(atype2),sizeof(atype3))
我怎样才能让预处理器计算MAX(sizeof,...)
,假设真的有十几种不同的联合类型?或者,是否有一种很好的清晰可读方式让预处理器在结构上制造不同的变体?
答案 0 :(得分:3)
有一种方法。它有点笨拙,但它的工作原理。您可能需要稍微调整一下。
首先创建一个头文件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;
};
答案 1 :(得分:1)
如果你不介意插入一堆反斜杠,这可以在没有单独的包含文件的情况下完成。但请阅读下面的警告,这也适用于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,差别很小)
但是要小心:如果union成员的对齐条件是由可能省略的元素的对齐而不是公共前缀的对齐,那么省略该元素可以减少union之前的填充,并且然后你会得到错误的尺寸。请参阅this snippet on coliru其中u3
已更改为long double
,结果是计算为SHORTER
的大小实际上小于联合的偏移量,这将导致不够空间被分配给较短的游泳池。