3

我想用 X-Macro 生成一个枚举。枚举必须根据 prev 大小增加。

我有这个

#define LIST
VAR(one, 0x02)
VAR(two, 0x02)
VAR(tree, 0x03)

并想生成这个

enum{
one = 0x02 + 0,
two = 0x02 + one,
tree = 0x03 + two
}

但这不起作用

#define VAR(NAME, SIZE) STORED_LOCATION_##NAME = SIZE + (STORED_LOCATION_##NAME-1)
enum{STORED_VARIABLES};
#undef VAR

这行得通,但我觉得它可以更容易

#define LIST \
VAR(one     ) STR(STORED_LOCATION   )\
VAR(two     ) PRE(one           )\
VAR(tree    ) PRE(two           )\
VAR(fore    ) PRE(tree          )\

enum
{
    one     = 0x00,
    two     = 0x01 + one,
    tree    = 0x01 + two,
    fore    = 0x01 + tree,
};

#define STR(OFFSET) OFFSET,
#define PRE(NAME) sizeof(##NAME) + STORED_LOCATION_##NAME,
#define VAR(NAME) STORED_LOCATION_##NAME =
enum{STORED_VARIABLES};
#undef VAR
#undef PRE
#undef STR
4

2 回答 2

0

一个可行的半解决方案可能是声明一个等效的虚拟打包结构,然后使用它的字段的偏移量来获得所需的枚举值。

像那样(在gcc下工作):

文件“ my.def ”:

VAR(one, 0x02)
VAR(two, 0x02)
VAR(tree, 0x03)

声明结构和枚举:

#define VAR(NAME, SIZE) char NAME[SIZE];
typedef struct __attribute__ ((__packed__)) {
#include "my.def"
} myEnumStruct;
#undef VAR

#define VAR(NAME, SIZE) NAME = (offsetof(myEnumStruct, NAME) + sizeof(((myEnumStruct*)0)->NAME)),
typedef enum{
#include "my.def"
} myEnum;
#undef VAR

int main(int argc, char **argv) {
    myEnum t;
#define VAR(NAME, SIZE) t=NAME; printf("Value of " #NAME " is %i\n", t);
#include "my.def"
#undef VAR

    return EXIT_SUCCESS;
}

这给出了所需的:

一的值是 2 二
的值是 4
树的值是 7


祝你好运!

于 2017-02-16T22:06:04.600 回答
0

您的问题令人困惑,因为您的第二个示例输出与您的第一个(所需)输出不匹配。此外,您的第一个输出可能不是您真正想要的,因为实际生成的枚举是随后的偏移量。更有可能的是,您希望生成充当命名字段偏移量的枚举:

enum
{
    one = 0,
    two = 2,
    tree = 4
};

以下代码本质上是使用我通常用于创建偏移量的宏生成的(请注意,它可以自由地穿插在普通枚举中):

//This macro makes it easy to define an enumeration that defines an offset, rather than
// an increment. The enumTag represents the offset and the size forces the following
// enumeration tag to be offset by that amount, rather than 1.
// _ignore##enumTag creates a throwaway enumeration that only exists to perform the offset.
#define ENUM_OFFSET(enumTag, size) enumTag, _ignore##enumTag = enumTag + (size) - 1

//VAR_(enumTag, size)
#define VAR_LIST(VAR_)
    VAR_(one  ,0x02)
    VAR_(two  ,0x02)
    VAR_(tree ,0x03)

enum 
{
    VAR_LIST(ENUM_OFFSET)
};

如果你真的想要(这看起来很奇怪):

enum
{
    one = 2,
    two = 4,
    tree = 7
};

您必须重新制定偏移宏。

#define ENUM_END_OFFSET(enumTag, size) _ignore1##enumTag, enumTag = _ignore1##enumTag + (size), _ignore2##enumTag = enumTag - 1,
enum 
{
    VAR_LIST(ENUM_END_OFFSET)
};
于 2017-04-25T16:45:58.723 回答