C 基于上一个值的X宏枚举

C 基于上一个值的X宏枚举,c,enums,c-preprocessor,x-macros,C,Enums,C Preprocessor,X Macros,我想用X宏生成一个枚举。枚举必须根据上一个大小递增 我有这个 #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

我想用X宏生成一个枚举。枚举必须根据上一个大小递增

我有这个

#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

一个有效的半解决方案可能是声明一个等效的伪压缩结构,然后使用其字段的偏移量来获得所需的枚举值

这样(在gcc下工作):

文件“my.def”:

声明结构和枚举:

#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



祝你好运

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

enum
{
    one = 0,
    two = 2,
    tree = 4
};
下面的代码本质上是使用我通常用于创建偏移量的宏生成的(请注意,它可以自由地散布在普通枚举中):

如果你真的想要(这似乎很奇怪):

必须重新格式化偏移量宏

#define ENUM_END_OFFSET(enumTag, size) _ignore1##enumTag, enumTag = _ignore1##enumTag + (size), _ignore2##enumTag = enumTag - 1,
enum 
{
    VAR_LIST(ENUM_END_OFFSET)
};
//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)
};