2016-07-22 31 views
3

Ich möchte eine enum mit einem X-Makro generieren. Das Enum muss basierend auf der vorherigen Größe zunehmen.X-Makro-Enumeration basierend auf dem vorherigen Wert

Ich habe diese

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

und wollen diese

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

erzeugen, aber dies nicht

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

Dies funktioniert funktioniert, aber ich, was es kann einfacher

#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 

Antwort

0

Eine funktionierende Semi-Lösung könnte sein, eine äquivalente Dummy-gepackte Struktur zu deklarieren und dann die Offsets ihrer Felder zu verwenden, um die gewünschten Enum-Werte zu erhalten.

Wie das (Arbeiten unter gcc):

File "my.def":

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

Deklarieren Struktur und Enum:

#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; 
} 

, die die gewünschte gibt:

Wert eines 2
Wert von zwei 4
Wert des Baumes 7


Viel Glück ist!

0

Ihre Frage ist verwirrend, weil Ihre zweite Beispielausgabe nicht mit Ihrer ersten (gewünschten) Ausgabe übereinstimmt. Außerdem ist Ihre erste Ausgabe wahrscheinlich nicht das, was Sie wirklich wollen, da es sich bei den erzeugten Enums um die folgenden Offsets handelt. Wahrscheinlicher ist, würden Sie Aufzählungen, die wirken, als Offsets zu dem Namen Felder erzeugen:

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

Der folgende Code im Wesentlichen erzeugt, dass ein Makro ich verwenden in der Regel für die Erstellung von Offsets (beachten Sie, dass es sich frei mit normalen Aufzählungen durchsetzt sein kann mit):

//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) 
}; 

Wenn Sie wirklich wollen (was) merkwürdig erscheint:

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

Sie müssen den Offset-Makro neu zu formulieren.

#define ENUM_END_OFFSET(enumTag, size) _ignore1##enumTag, enumTag = _ignore1##enumTag + (size), _ignore2##enumTag = enumTag - 1, 
enum 
{ 
    VAR_LIST(ENUM_END_OFFSET) 
};