3

Considering the following code snippet:

enum test {
        A,
        B,
        C
};

static const char *const table[] = {
        [A] = "A",
        //[B] = "B",
        [C] = "C",
}; // the string representation is not (always) equivalent to the enum identifier

If I accidentally miss an entry (B in this case), I'd like to get a compiler warning or error.

Tried with clang -Weverything and multiple gcc warnings (but no warning - compiles silently).

Also sizeof table / sizeof *table is still 3.

Or is there a way in C to check at compile time that all array elements are non-NULL?

// C++ variant
constexpr bool is_array_nonnull(const char *const array[]) {
        for (int i = 0; i <= sizeof array / sizeof *array; ++i)
                if (array[i] == nullptr)
                        return false;
        return true;
}
static_assert(is_array_nonnull(table));

edit: make requirements and tested steps more clear

theo
  • 39
  • 3
  • 1
    Why would you expect the compiler to issue a warning for that? It's completely valid and in compliance with the standard. – bool3max Dec 21 '19 at 19:30
  • 1
    @bool3max: There are all kinds of instances where a compiler is able to issue a warning for code that is valid and standard-compliant, yet probably not what the programmer intended, and this can be very helpful. Code like `if (x = 0) { ... }`, for instance. – Nate Eldredge Dec 21 '19 at 19:41
  • 1
    Though it doesn't *direcly* answer to your question, and trying to guess your actual goal, I think tha this answer can help you: https://stackoverflow.com/questions/9907160/how-to-convert-enum-names-to-string-in-c – Roberto Caboni Dec 21 '19 at 21:13
  • given your statement; `and multiple gcc warnings.`, indicates your code does not compile. What were those warnings? – user3629249 Dec 21 '19 at 22:31

2 Answers2

1

In order to prevent such kind of situations, you can use a technique called X Macro.

#define TESTLIST  X(A), X(B), X(C)

#define X(item) item
enum test { TESTLIST };
#undef X

#define X(item) [item] = #item
static const char *const table[] = { TESTLIST };
#undef X

which expands to

enum test { A, B, C };
static const char *const table[] = { [A] = "A", [B] = "B", [C] = "C" };

When you add an item to (or delete from) the list you only need to modify the TESTLIST macro. The rest of the code remains the same.

Lxer Lx
  • 292
  • 1
  • 6
0

For the time being I am using a "unit test", which checks with a runtime function that every field of the lookup table is properly initialized (non-null).

theo
  • 39
  • 3