1

Two developers are writing two units currently. The one unit contains an enumeration definition (which is additionally dependent on compiler switches) , the other one uses the array definition to initialize an array. Currently everything is in sync. How can we avoid to get into trouble if the definition of the enumeration is changed over time, but the array is not. Any ideas for compile time or runtime checks?

abc.h

typedef enum {
  A,
  #ifdef UseB
  B,
  #endif
  C,
  MAX
}My Enum

xyz.c

#include abc.h
int myArray[MAX] = {
  1,    // A
  #ifdef UseB
  2,    // B
  #endif
  3
};

Is there a way to get a notification if a new element D is added after C or if the order changes (e.g. A and C are interchanged)?

  • IMO, you should be bothered about deletion, not addition in `enum`, keeping array unchanged. – Sourav Ghosh Nov 20 '14 at 09:51
  • possible duplicate of [Detecting mismatched array <-> enum initializers](http://stackoverflow.com/questions/10446827/detecting-mismatched-array-enum-initializers) – user694733 Nov 20 '14 at 10:30
  • You could use an `assert_compile` to check that the size actually matches – n0p Nov 20 '14 at 10:47
  • @SouravGhosh Deleting an enumeration element without adapting the array should lead to a compiler error as there are more initialization elements in the array than the size of the array. But the compiler won't necessarily complain if there are too less initialization values (due to addition of enumeration members). – Jochen Widmaier Nov 20 '14 at 13:48
  • @user694733: The linked questions solves part of the problem. It takes care of detecting more elements in the enum than initialization values in the array. There is one difference in my example compared to the other question. Our arrays are always declared with the necessary size. Therefore the size of the array will always fit (with probably uninitialized array elements). But maybe we should not add the size for the array elements, but therefore a check if the number of initialization values matches to the number of enumeration values. – Jochen Widmaier Nov 20 '14 at 13:53
  • @JochenWidmaier On selected answer it's not explicitly stated, but size of array should be left out. Then you will catch the inconsistencies with both; too long or short arrays. In addition, if you need to `MAX` to be in specific range, you could have another static assertion for that. – user694733 Nov 20 '14 at 14:14

3 Answers3

3

Define the entire enum contents in a macro:

#ifdef UseB
#define B_Contents B,
#else
#define B_Contents 
#endif

#define MYENUM_CONTENT \
A, \
B_Contents \
C

typedef enum {
    MYENUM_CONTENT , 
    MAX
}

xyz.c:

#include abc.h
int myArray[MAX] = {
  MYENUM_CONTENT
};
Sergey L.
  • 21,822
  • 5
  • 49
  • 75
  • I'm not sure if this answers the question. Answer seems to assume that array should contain the same data as enumeration, but question has differing data. And if they were the same, what would be the point of array in the first place? – user694733 Nov 20 '14 at 10:55
  • @sergey-l The content of the array indeed differs from the enumeration values. Therefore your answer does not fit to my problem. But thank you for your answer. – Jochen Widmaier Nov 20 '14 at 13:54
0

You can put them together in the same include so that updating 1 prompts updating the other. Here is an example from musl libc:

strerror.h

E(EILSEQ,       "Illegal byte sequence")
E(EDOM,         "Domain error")
E(ERANGE,       "Result not representable")
E(ENOTTY,       "Not a tty")
E(EACCES,       "Permission denied")
E(EPERM,        "Operation not permitted")
E(ENOENT,       "No such file or directory")
E(ESRCH,        "No such process")
E(EEXIST,       "File exists")
//....

strerror.c

#define E(a,b) ((unsigned char)a),
static const unsigned char errid[] = {
#include "__strerror.h"
};

#undef E
#define E(a,b) b "\0"
static const char errmsg[] =
#include "__strerror.h"
technosaurus
  • 7,676
  • 1
  • 30
  • 52
  • Interesting idea. But this only works out, if the usage of the enum is very limited. If the enum is used for - lets say - 10 arrays. You would have to have ten columns. And we allow more or less everybody to use the enum whenever needed. Might make it hard if four people have to maintain the h-file. Thank you for this answer. – Jochen Widmaier Nov 20 '14 at 14:04
-1

Manually assign values in enum and initialize the array with enum labels:

typedef enum {
  A = 1,
  #ifdef UseB
  B = 2,
  #endif
  C = 3,
}My Enum

int myArray[MAX] = {
  A,
  #ifdef UseB
  B,
  #endif
  C
};

But you'd have to define MAX conditionally, which looses the elegance of having it a part of the enum:

#ifdef UseB
#define MAX 3
#else
#define MAX 2
#endif
Tomo
  • 3,431
  • 5
  • 25
  • 28