cenums

Get maximum of enum in pure C


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?


Solution

  • 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)