Assuming I have a code like this:
#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;
}
Is there a way to auto-calculate a MAX_COLOR_CODE
define?
One easy & readable way to do it is to create a typedef union
based on the X macro and populate it with character arrays. The size of the union is then corresponding to the largest item.
#include <stdio.h>
#define COLORS(X) \
X(RED, 10) \
X(GREEN, 2) \
X(BLUE, 5) \
X(YELLOW, 7)
typedef union
{
#define UNION_MEMB(col, n) char memb_##col [n];
COLORS(UNION_MEMB)
} max_color_t;
#define MAX_COLOR_CODE sizeof(max_color_t)