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));
}
Related
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.
I cannot find something similar to this.
#define ONE 1
#define TWO 2
int main()
{
int x = ONE;
printf("%s \n", x);
}
//the desirable output will be "ONE"
Now, I saw the other answers with the
#define PRINT(X) printf("%s \n", #x);
and I did not find how to use it to get what I want.
There is no direct way to do this. The only information you have in your printf call is a variable x whose current value happens to be 1 (at run time), which happens to be the expansion of a macro whose name is ONE. There is no way for the compiler to figure out the name ONE from that information. There might be several different macros with the same definition, or there might not be any.
If you want to print the string ONE given the integer value 1, you're going to have to set up some kind of lookup table or function. For example:
const char *const names[] = { "ZERO", "ONE", "TWO", "THREE", "FOUR", /* etc. */ };
printf("%s\n", names[x]);
It would be entirely up to you to get the names right, so that for example 1 doesn't map to "THREE".
As #KeithThompson said, there is no easy way.
But there is a clever hack which does more or less what you ask for.
#define MY_ENUM_LIST \
X( ONE , 1 ) \
X( TWO , 2 ) \
X( THREE , 3 )
#define X(name, value) name = value,
enum MyEnum {MY_ENUM_LIST};
#undef X
const char *my_enum_to_str(enum MyEnum e)
{
switch (e)
{
#define X(name, value) case value: return #name;
MY_ENUM_LIST
#undef X
default:
return "<invalid>";
}
}
int main()
{
int x = ONE;
printf("%d\n", x); // prints "1"
printf("%s\n", my_enum_to_str(x)); // prints "ONE"
return 0;
}
It has following advantages over the naïve lookup table:
No need to repeat enumerator names twice.
You can have any enumerator values, not only a contiguous range.
You can't accidentaly assign an incorrect name to an enumerator.
I am trying to define a constant that would have the following in it
ch[co].gold < 10000*100
how can I make it, something like
define x = ch[co].gold < 10000*100;
so that every time I write
if (x) {say(cn,"You need 10 000 gold coins");}
Or that is not possible?
Function:
int x(int val) {
return (val < 10000 * 100);
}
Usage
// ...
if (x(ch[co].gold)) {
printf("You need 10 000 gold coins.\n");
}
// ...
Well, here is my solution
struct s {
int gold;
};
const int co = 2;
struct s ch[] = {112,2321,3234};
#define x() ch[co].gold < 10000*100
int main(){
if (x()) {
}
return 0;
}
Is this what you are expecting?
#define x (ch[co].gold < 10000*100)
Add this line of code before the place you use it, usually it's just below the #includes.
Conventionally, we use capital letters with clearer meanings instead of x.
#define is simply text substition performed by the preprocessor.
To do what you say you want use the following #define:
#define x ch[co].gold < 10000*100
Every time the preprocessor encounters the symbol x it will replace it with ch[co].gold < 10000*100.
I think that what you really want is to make it a proper function as suggested by pmg. It is a wiser choice.
Consider the following code i managed to write:
#include <stdio.h>
#define FOR(A, B, C) for(A; B; C++)
int main()
{
FOR(i=0, i<10, i)
printf("%i", i);
return 1;
}
The output is:
0123456789
If i do FOR(i=5, i<10, i)
then respectively the output is 56789
My questions are is that legal? Will it cause any errors in different cases? Does it works exactly like a for loop?
Yes it's a "legal" macro, but no, it does not work like a real for loop.
Your macro won't handle this:
int a, b;
for(a = 0, b = 4711; a < b; ++a);
for instance, since you can't distinguish the , used to build a longer initializing expression to the one used to separate the expressions that make up the parts:
FOR(a = 0, b = 0, a < b, ++a);
will break, since it looks like a call with 4 arguments instead of 3.
A macro is just copied everywhere the preprocessor sees you using the macro keyword. It just copies the text, nothing more.
To elaborate on that a bit more, consider this example:
#define MY_MACRO a
int MY_MACRO = 5;
When the preprocessor comes along it will take the above and change it to:
int a = 5;
and then the compiler will come along and compile it like normal C/C++ code.
When you add arguments to your macro, they are just substituted in place within your macro. This can be a problem, consider the following two macros:
#define BAD_MACRO(a, b) a*b
#define GOOD_MACRO(a, b) (a)*(b)
They look almost the same, but consider the following:
int k = BAD_MACRO(2, 3); // k = 2*3 = 6
int j = GOOD_MACRO(2, 3); // j = 2*3 = 6
int m = BAD_MACRO(2+1, 3); // m = 2+1*3 = 5
int n = GOOD_MACRO(2+1, 3); // n = (2+1)*3 = 9
Although note that neither of these macros are good or bad, they just don't have the same behaviour as a typical function.
I use a struct of bit fields to access each colour channel in a pixel, the problem is that quite often I have code that applies in the same way to each channel, but because I cannot just iterate over the members of a struct in C I end up having 3 copies of the same code for each member, or more inconveniently have to use switch-case statements.
I figured it would be more elegant if I could use a macro so that I can access a member by providing a number, ideally a macro that would make .CHAN(i) become either .r, .g or .b depending on whether the integer variable i contains a 0, 1 or 2. Except I have no idea how one would make such a macro or even if that's possible.
A detail but each member is something like 12 bits, not 8 as one might expect, so I cannot just turn it into an array or have a union with a pointer. Also X-Macros won't do as I often need to do many things to each channel before doing the same to another channel, in other words the for loop for going through each member can contain a lot more than just one line.
EDIT: Here's some code, first the struct:
typedef struct
{
uint32_t b:12;
uint32_t g:12;
uint32_t r:12;
uint32_t a:12;
} lrgb_t;
Now an example of what my problem looks like in code:
for (ic=0; ic<3; ic++)
{
for (i=0; i<curvecount; i++)
{
curve[i].p0.x = (double) i;
curve[i].p3.x = (double) i+1.;
switch (ic) // this is what I'm trying to eliminate
{
case 0:
curve[i].p0.y = pancol[i].r / 4095.;
curve[i].p3.y = pancol[i+1].r / 4095.;
break;
case 1:
curve[i].p0.y = pancol[i].g / 4095.;
curve[i].p3.y = pancol[i+1].g / 4095.;
break;
case 2:
curve[i].p0.y = pancol[i].b / 4095.;
curve[i].p3.y = pancol[i+1].b / 4095.;
break;
}
// Ideally this would be replaced by something like this, CHAN() being an hypothetical macro
// curve[i].p0.y = pancol[i].CHAN(ic) / 4095.;
// curve[i].p3.y = pancol[i+1].CHAN(ic) / 4095.;
}
... // more stuff that ultimately results in a bunch of pixels being written, channel after channel
}
as pointed out in the comments, this doesn't really address the OP's problem because the members on his struct are bitfields that wouldn't align with an array. I'll keep the answer here though, in hopes it can still be useful to someone.
I think a union is what you want.
You can write your struct such as
union
{
struct
{
float r;
float g;
float b;
}rgb;
float channel[3];
} color;
This way the struct will be in the same place in memory as the float[3], and you can effectively access the same members as either a struct member or as an element in the array.
You might have to look up the exact syntax, but you get the idea.
One possibility might be to wrap the repeated code into a function, and then call it for each of the channels:
typedef struct {
int r:12;
int g:12;
int b:12;
} Pixel;
int inc(int val) {
return val + 1;
}
int main(void) {
Pixel p = {0, 0, 0};
p.r = inc(p.r);
p.g = inc(p.g);
p.b = inc(p.b);
return 0;
}
After reading the code that you added I made some changes to my suggested macro
#define CHAN(ic) \
(ic == 1) ? curve[i].p0.y = pancol[i].r / 4095; curve[i].p3.y = pancol[i+1].r / 4095; : \
(ic == 2) ? curve[i].p0.y = pancol[i].g / 4095; curve[i].p3.y = pancol[i+1].g / 4095; : \
curve[i].p0.y = pancol[i].b / 4095; curve[i].p3.y = pancol[i+1].b / 4095;
The macro CHAN(ic) will evaluate 'ic' in order to decided which member to manipulate. If 'ic' is 1 then the member '.r' will be manipulated if 'ic' is 2 then '.g' will be manipulated, and if 'ic' is neither 1 or 2 then '.b' will be manipulated because of this assumption you must make sure that 'ic' is properly set otherwise you could screw with the value of panco[i].b and pancol[i+1].b . You code should look something like the following but you will most likely need to tweak the macro a bit let me know if you have any questions.
//#define CHAN(ic) here
for (ic=0; ic<3; ic++)
{
for (i=0; i<curvecount; i++)
{
curve[i].p0.x = (double) i;
curve[i].p3.x = (double) i+1.;
CHAN(ic)
}
... // more stuff that ultimately results in a bunch of pixels being written, channel after channel
}
Also please note that my macro will do exactly the same thing as your switch case. The only difference is that it is defined in a macro the point I am trying to make is that the difference between the switch case and the macro is purely visual.