2016-07-22 1 views
3

Je souhaite générer une énumération avec une macro X. L'enum doit augmenter en fonction de la taille de prev.X-macro enum basé sur la valeur précédente

Je possède ce

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

et que vous voulez générer ce

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

mais cela ne fonctionne pas

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

Cela fonctionne, mais je chose, il peut être plus facile

#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 

Répondre

0

Une semi-solution de travail pourrait consister à déclarer une structure factice équivalente et à utiliser les décalages de ses champs pour obtenir les valeurs d'énumération désirées.

Comme ça (travaillant sous gcc):

Fichier "my.def":

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

Déclarant struct et 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; 
} 

Ce qui donne le Souhaité:

Valeur de l'un est 2
Valeur de deux est 4
Valeur d'arbre est 7


Bonne chance!

0

Votre question est source de confusion car votre deuxième exemple de sortie ne correspond pas à votre première sortie (souhaitée). De plus, votre premier résultat n'est probablement pas ce que vous voulez vraiment, car les enumérations générées sont en fait les compensations qui suivent. Plus probablement, vous voulez générer énumérations qui agissent comme des compensations aux champs nommés:

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

Le code suivant génère essentiellement que l'utilisation d'une macro que j'utilise généralement pour créer des décalages (notez qu'il peut être librement entrecoupé de énumérations normales):

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

Si vous voulez vraiment (ce qui semble bizarre):

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

vous devez reformuler la macro offset.

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