How to define size of enum minus one element - c

if I have enum:
typedef enum
{
A= 0,
B= 1,
C =2,
D= 4,
E= 6,
F= 8,
G= 10,
MAX_ELEMENTS
}my_enum
How can I declare the number of elements within enum without one element?
something like this:
uint8 enum_numb_elements = MAX_ELEMENTS - 1
This is not a good practice to do arithmetic operation on enums. Is there an other way?

You can define it, sort of, but it involves some boiler-plate that isn't all too pleasant, and pollutes the global/tag namespace a lot/bit.
If you leverage the notorious X macros for the job, it would look like this:
#define LIST_OF_ENUM_IDS \
X(A, 0) \
X(B, 1) \
X(C, 2) \
X(D, 4) \
X(E, 6) \
X(F, 8) \
X(G, 10)
#define X(id, val) \
id = val,
typedef enum
{
LIST_OF_ENUM_IDS
} my_enum;
#undef X
#define X(id, val) id##_impl_helper,
enum my_enum_impl_helper__ {
LIST_OF_ENUM_IDS
MY_ENUM_MAX_ELEMENTS
};
#undef X
Live example: On Ideone
Alternatively, some shops will instead rely on bold comments and code reviews to catch such things:
/********************************************
*
**
*** ATTENTION! Remember to bump MAX_ELEMENTS
*** should you add new values to the enum
**
*
********************************************/
typedef enum
{
A= 0,
B= 1,
C =2,
D= 4,
E= 6,
F= 8,
G= 10,
MAX_ELEMENTS = 7 /// Bump this if you add new values!
}my_enum;
Which can work not all too bad, despite the human factor.

I prefer to keep enums contiguous to exploit the 'features' of C..
typedef enum
{
A,
B,
C,
D,
E,
F,
G,
MAX_ELEMENTS
} my_enum;
int element_array[MAX_ELEMENTS] =
{
0,
1,
2,
4,
6,
8,
10
};
Given this construct, NUM_ELEMENTS adjusts automatically if you add/subtract enums, and you can use my_elem in for loops, etc. The major issue of concern is that you need to remember to maintain element_array in conjunction with my_enum when you add or remove enums.
A for loop example
my_elem elem;
for (elem = (my_elem)0; elem < MAX_ELEMENTS; elem++)
{
printf("The value of element %d is %d\n", elem, element_array[elem] );
}

Related

Can a C program determine a macro identifier/enum name based on its value?

Let's say we define some error codes as macros -
#define ERR_SUCCESS 0
#define ERR_BAD_INPUT 1
...
or as an enumerated data type -
enum err_t = { ERR_SUCCESS, ERR_BAD_INPUT, ...};
and one of these ids is returned by a function such as -
int foo(); /* if foo() returns 0, it means success, etc */
Can the caller of foo() determine which identifier / name (ERR_SUCCESS, ERR_BAD_INPUT, ...) is linked to the int return value?
No.
Processor macros, as the name suggested, are resolved while preprocessing before the compilation step starts. While calling, i.e. during run time, there is no reference to the names like ERR_SUCCESS, ERR_BAD_INPUT etc. and that's why you can't determine the identifier name at run time.
Simliar reasoning goes for enum too since enum creates compile time constants and you can't get the identifier name during run time.
Not directly, as pointed out by others those identifiers are not available at runtime, but you can use a parallel list of names (an X Macro can help):
#include <stdio.h>
#define ERRS \
X(ERR_SUCCESS) \
X(ERR_BAD_INPUT) \
X(ERR_MORE)
#define X(x) x,
enum err_t {ERRS};
#undef X
#define X(x) #x,
static char *err_name[] = {ERRS};
#undef X
static int foo(void)
{
/* ... */
return ERR_BAD_INPUT;
}
int main(void)
{
printf("%s\n", err_name[foo()]);
return 0;
}
Output:
ERR_BAD_INPUT
Since C99, Keine Lust's macros could even be extended to set values explicitly:
#define X(x) x,
#define X_WITH_VALUE(x, v) x = v,
and:
#define X(x) [x] = #x,
#define X_WITH_VALUE(x, v) X(x)
finally a function:
char const* getName(enum E e)
{
char const* n = e < sizeof(arr)/sizeof(*arr) ? arr[e] : NULL;
return n ? n : "<unknown error>";
}
Edit (in response to comment): Assigning values explicitly allows to introduce
(desired!) gaps and synonyms:
enum Flags
{
None = 0,
F0 = 1,
F1 = 2,
F2 = 4,
F3 = 8,
G3 = F3,
}
This will result in gaps in the array, though, resulting in necessity for the null pointer check in the function. If your enum values get large, the array might get huge, so the array solution might not be suitable any more...
The synonyms impose another problem, see Jens's answer. The problem is solved partially, code does work, but you do not necessarily get back the synonym originally used, but always the last defined one instead! In above example, this would be G3 even if you used F3 in your code. So you have to define the desired synonym last (which seems a little unnatural to me...) or you use the SYNONYM macro below.
Some special cases with array size might be solved with additional tricks, e. g. if you have subsequent values with a higher start value:
#define X(x) [x - Initial] = #x,
char const* n = e < sizeof(arr)/sizeof(*arr) ? arr[e - Initial] : NULL;
Interesting gets the powers of two enum above:
#define X(x, p) x = (1 << p),
enum err_t {None = 0, ERRS};
char const* getName(enum E e)
{
if(e == None)
return S(None); // stringification macro, yet to be defined
// check, if power of two:
if((unsigned int) e & ((unsigned int) e - 1))
{
int index = log2(e);
if(index < sizeof(arr)/sizeof(*arr)
return arr[index];
}
return "<unknown>";
}
The power of two check is coming from Sean Eron Anderson (here exactly), you find nice solutions to calculate log2 there, too, e. g. this one.
Completely different approach, suitable for any kind of distinct values (but synonyms need to be handled explicitly!):
#define X(x) x,
#define X_WITH_VALUE(x, v) x = v,
#define SYNONYM(y, x) y = x,
#define X(x) case x: return #x;
#define X_WITH_VALUE(x, v) X(x)
#define SYNONYM(y, x)
char const* getName(enum E e)
{
switch(e)
{
ERRS
default:
return "<unknown>";
}
}
No. This is easy to see when you realize the mapping from values to names is not bijective. Which is a fancy way to say that macros such as
#define ZERO 0
#define ZILCH 0
#define NADA 0
#define NIENTE 0
are allowed to coexist. Given 0, which is the associated name?
The same argument applies to enum identifiers.
No, it's not supported by the compiler. The compiler gets the output of the C preprocessor with the #defines replaced by there values. You need to detect the values in your code. e.g. like in this question.

Access an enum using an index in C

Consider:
enum Test
{
a = 3,
b = 7,
c = 1
};
I want to access the enum using an index. Something like this:
for (i=0; i<n; i++)
doSomething((Test)i);
How can I do something like this, where I will be able to access the enum using an index, though the members of the enum have different values?
This is the best you can do:
enum Test { a = 3, b = 7, c = 1, LAST = -1 };
static const enum Test Test_map[] = { a, b, c, LAST };
for (int i = 0; Test_map[i] != LAST; i++)
doSomething(Test_map[i]);
You have to maintain the mapping yourself.
You can't do that. A C enum is not much more than a bunch of constants. There's no type-safety or reflection that you might get in a C# or Java enum.
Your question demonstrates you don't really understand what an enum is for.
It is not something that can be indexed, nor is there ever any reason to. What you have defined is actually just 3 constants named a, b, and c, whose values are 3, 7, and 1 respectively.
As someone else mentioned, this is not the purpose of an enum. In order to do what you are asking, you can simply use an array:
#define a 3
#define b 7
#define c 1
int array[3] = { a, b, c };
int i;
for( i = 0; i < sizeof(array)/sizeof(array[0]); i++ ) {
doSomething( array[i] );
}

How to get an array size

I'd like to know how to get an array rows & columns size. For instance it would be something like this:
int matrix[][] = { { 2, 3 , 4}, { 1, 5, 3 } }
The size of this one would be 2 x 3. How can I calculate this without including other libraries but stdio or stdlib?
This has some fairly limited use, but it's possible to do so with sizeof.
sizeof(matrix) = 24 // 2 * 3 ints (each int is sizeof 4)
sizeof(matrix[0]) = 12 // 3 ints
sizeof(matrix[0][0]) = 4 // 1 int
So,
int num_rows = sizeof(matrix) / sizeof(matrix[0]);
int num_cols = sizeof(matrix[0]) / sizeof(matrix[0][0]);
Or define your own macro:
#define ARRAYSIZE(a) (sizeof(a) / sizeof(a[0]))
int num_rows = ARRAYSIZE(matrix);
int num_cols = ARRAYSIZE(matrix[0]);
Or even:
#define NUM_ROWS(a) ARRAYSIZE(a)
int num_rows = NUM_ROWS(matrix);
#define NUM_COLS(a) ARRAYSIZE(a[0])
int num_cols = NUM_COLS(matrix);
But, be aware that you can't pass around this int[][] matrix and then use the macro trick. Unfortunately, unlike higher level languages (java, python), this extra information isn't passed around with the array (you would need a struct, or a class in c++). The matrix variable simply points to a block of memory where the matrix lives.
It cannot be "something like this". The syntax that involves two (or more) consecutive empty square brackets [][] is never valid in C language.
When you are declaring an array with an initializer, only the first size can be omitted. All remaining sizes must be explicitly present. So in your case the second size can be 3
int matrix[][3] = { { 2, 3, 4 }, { 1, 5, 3 } };
if you intended it to be 3. Or it can be 5, if you so desire
int matrix[][5] = { { 2, 3, 4 }, { 1, 5, 3 } };
In other words, you will always already "know" all sizes except the first. There's no way around it. Yet, if you want to "recall" it somewhere down the code, you can obtain it as
sizeof *matrix / sizeof **matrix
As for the first size, you can get it as
sizeof matrix / sizeof *matrix
sizeof (matrix) will give you the total size of the array, in bytes. sizeof (matrix[0]) / sizeof (matrix[0][0]) gives you the dimension of the inner array, and sizeof (matrix) / sizeof (matrix[0]) should be the outer dimension.
Example for size of :
#include <stdio.h>
#include <conio.h>
int array[6]= { 1, 2, 3, 4, 5, 6 };
void main() {
clrscr();
int len=sizeof(array)/sizeof(int);
printf("Length Of Array=%d", len);
getch();
}

C array initialization via macro

Question's Background:
void dash(int *n, char c) is to draw characters c separated by '+'.
Parameter n is an array of ints, e.g. {1, 3, 2} and '-' for c should give "+-+---+--+", which works fine.
To use dash I do {int f={1, 3, 2}; dash(f, '-');}, which makes the construct copy&pastable.
The question itself:
To avoid copy&pasting I wanted to do #define F(X, Y) {int f=X; dash(f, Y);},
resulting in a nicely usable F({1, 3, 2}, '-').
Unfortunately the compiler complains about F getting 4 (array's length + 1) arguments instead of 2.
So how can you give {1, 3, 2} as parameter to a macro?
Variadic macros are a feature of C99.
#define F(Y,...) dash((int[]){__VA_ARGS__},Y)
So how can you give {1, 3, 2} as
parameter to a macro?
F('-',1,3,2);
Here is my version:
#include <stdio.h>
void dash(int len, int *n, char c){
int i;
printf("dash( %i, {", len );
for( i=0; i<len-1; i++ )
printf(" %i,", n[i] );
printf(" %i }, '%c')\n", n[i], c );
}
#define NOPAREN(...) __VA_ARGS__
#define F1(arr,char) { int f[]={NOPAREN arr}; dash(sizeof(f)/sizeof(f[0]),f,char); }
#define F2(char,...) { int f[]=__VA_ARGS__; dash(sizeof(f)/sizeof(f[0]),f,char); }
int main(void){
F1( (1,3,2), '-' );
F2( '-', {4,6,5} );
}
Result:
dash( 3, { 1, 3, 2 }, '-')
dash( 3, { 4, 6, 5 }, '-')
Instead of trying to use a macro to set up and make these calls, I'd probably consider changing the interface to dash() to use varargs:
#include <stdarg.h>
void dash( char c, ...)
{
// ...
}
int main() {
dash( '+', 1, 3, 2, -1); // note: negative number indicates
// the end of the list of numbers
return 0;
}
Using varargs isn't the best thing in the world (they're difficult to use and aren't typesafe), but I think it would be better than the macro concoction you're trying to gen up.
Also, remember that even if you stick with your current interface for dash() and come up with a macro that does what you want, you still need to have a way to indicate the end of the sequence of numbers to be passed into dash(). Otherwise there's no way for dash to know when it has reached the end of the array. You have several choices:
use a sentinel value, such as 0, -1, or any negative number (like in the vararg example above)
pass the number of elements in the array as another argument
set the size of the array as a part of dash()'s interface. In your example, dash() might require that an array of 3 ints be passed in. No more, no less (actually more would be OK - they just wouldn't be used). If you did this, fixing your macro would be much easier, but I suspect it's not how you want dash to behave.
You can pass { 1, 3, 2 } as an argument to a macro if you define { 1, 3, 2 } as another macro
#define PARAMS { 1, 3, 2 }
F(PARAMS, '-')
#undef PARAMS
Unfortunately, there seems to be no direct way to do literally what you ask, i.e. pass specifically { 1, 3, 2 } in this specific form. It might be worth switching to alternative methods, including the C99-specific ones suggested in other answers.

Number of elements in an enum

In C, is there a nice way to track the number of elements in an enum? I've seen
enum blah {
FIRST,
SECOND,
THIRD,
LAST
};
But this only works if the items are sequential and start at zero.
If you don't assign your enums you can do somethings like this:
enum MyType {
Type1,
Type2,
Type3,
NumberOfTypes
}
NumberOfTypes will evaluate to 3 which is the number of real types.
I don't believe there is. But what would you do with such a number if they are not sequential, and you don't already have a list of them somewhere? And if they are sequential but start at a different number, you could always do:
enum blah {
FIRST = 128,
SECOND,
THIRD,
END
};
const int blah_count = END - FIRST;
Old question, I know. This is for the googlers with the same question.
You could use X-Macros
Example:
//The values are defined via a map which calls a given macro which is defined later
#define ENUM_MAP(X) \
X(VALA, 0) \
X(VALB, 10) \
X(VALC, 20)
//Using the map for the enum decl
#define X(n, v) [n] = v,
typedef enum val_list {
ENUM_MAP(X) //results in [VALA] = 0, etc...
} val_list;
#undef X
//For the count of values
#define X(n, v) + 1
int val_list_count = 0 + ENUM_MAP(X); //evaluates to 0 + 1 + 1 + 1
#undef X
This is also transparent to an IDE, so auto-completes will work fine (as its all done in the pre-processor).
Unfortunately, no. There is not.
I know this is a very old question, but as the accepted answer is wrong, I feel compelled to post my own. I'll reuse the accepted answer's example, slightly modified.
(Making the assumption that enums are sequential.)
// Incorrect code, do not use!
enum blah {
FIRST = 0,
SECOND, // 1
THIRD, // 2
END // 3
};
const int blah_count = END - FIRST;
// And this above would be 3 - 0 = 3, although there actually are 4 items.
Any developer knows the reason: count = last - first + 1.
And this works with any combination of signs (both ends negative, both positive, or only first end negative). You can try.
// Now, the correct version.
enum blah {
FIRST = 0,
SECOND, // 1
THIRD, // 2
END // 3
};
const int blah_count = END - FIRST + 1; // 4
Edit: reading the text again, I got a doubt. Is that END meant not to be part of the offered items? That looks weird to me, but well, I guess it could make sense...
Well, since enums can't change at run-time, the best thing you can do is:
enum blah {
FIRST = 7,
SECOND = 15,
THIRD = 9,
LAST = 12
};
#define blahcount 4 /* counted manually, keep these in sync */
But I find it difficult to envisage a situation where that information would come in handy. What exactly are you trying to do?
int enaumVals[] =
{
FIRST,
SECOND,
THIRD,
LAST
};
#define NUM_ENUMS sizeof(enaumVals) / sizeof ( int );
#include <stdio.h>
// M_CONC and M_CONC_ come from https://stackoverflow.com/a/14804003/7067195
#define M_CONC(A, B) M_CONC_(A, B)
#define M_CONC_(A, B) A##B
#define enum_count_suffix _count
#define count(tag) M_CONC(tag, enum_count_suffix)
#define countable_enum(tag, ...) \
enum tag {__VA_ARGS__}; \
const size_t count(tag) = sizeof((int []) {__VA_ARGS__}) / sizeof(int)
// The following declares an enum with tag `color` and 3 constants: `red`,
// `green`, and `blue`.
countable_enum(color, red, green, blue);
int main(int argc, char **argv) {
// The following prints 3, as expected.
printf("number of elements in enum: %d\n", count(color));
}

Resources