Supondo que eu tenha um código como este:
#include <stdio.h>
// A numbered enum with gaps
#define COLORS(X) \
X(RED, 10) \
X(GREEN, 2) \
X(BLUE, 5) \
X(YELLOW, 7)
typedef enum {
#define XX(N, M) CLR_##N = M,
COLORS(XX)
#undef XX
} colors_e;
// This define must have the highest value of enum
#define MAX_COLOR_CODE 10
typedef struct {
char *language;
// the define is needed for array definition inside a struct
char *colors[MAX_COLOR_CODE + 1];
} color_names_t;
// The array of struct is selectively filled at compile time, hence use of enum for indexing
color_names_t color_names[] = {
{"en", {[CLR_RED] = "red", [CLR_BLUE] = "blue", [CLR_GREEN] = "green"}},
{"du", {[CLR_BLUE] = "blau", [CLR_YELLOW] = "gelb", [CLR_RED] = "rot"}},
};
/// ---- a sample usage of the defined array of structs
#define ARR_SIZE(X) (sizeof(X)/sizeof(X[0]))
int main() {
for(int lidx=0; lidx<ARR_SIZE(color_names); lidx++) {
printf("Language: %s\n", color_names[lidx].language);
for(int idx=0; idx<ARR_SIZE(color_names[0].colors); idx++) {
if(color_names[lidx].colors[idx])
printf("\t%s\n", color_names[lidx].colors[idx]);
}
}
return 0;
}
Existe uma maneira de calcular automaticamente uma MAX_COLOR_CODE
definição?
Este código:
imprime o máximo, “10”.
Essa abordagem aproveita sua estrutura X-macro existente, tornando-a livre de manutenção. Ao adicionar/alterar valores de enumeração, MAX_COLOR_CODE será atualizado automaticamente. Não há necessidade de rastreamento manual ou cálculos separados.
O código a seguir retorna 10:
Ele cria um literal de array temporário como
(char[]){[10]=0,[2]=0,[5]=0,[7]=0}
e obtém seu tamanho. O tamanho dochar[]
array depende do índice máximo no array. O métodosizeof
não avalia o array, então ele está apenas no código do compilador.Isso não funcionará com números negativos. Mas você pode compensar os números
#define S(a,b) [b+INT_MAX]=0,
eCOLORS(S)}) - 1 - INT_MAX
.Uma maneira fácil e legível de fazer isso é criar uma união
typedef union
com base na macro X e preenchê-la com matrizes de caracteres. O tamanho da união corresponde ao maior item.Ter o último
enum
como..._N
é um padrão de codificação comum.Não é bem o que o OP solicitou, mas considere manter os valores em ordem crescente:
E então adicione mais um
enum
Adicione a definição da matriz como:
(Pode precisar de alguma correção mágica de macro, mas espero que a ideia seja bem apresentada.)