I have an enum like that:
enum {
ID_FOO = 0,
ID_BAR,
ID_BAZ
}
And a constant array using designated initializers like hat:
char* arr[] = {
[ID_FOO] = "foo stuff",
[ID_BAR] = "bar stuff",
[ID_BAZ] = "baz stuff",
0
}
Now when I add a value to the enum, e.g. after ID_FOO but forget to add it to the array, then I would get an uninitialized null-initialized 'hole' in the array. Is there any way to prevent that, or at least get a warning from the compiler?
A non-portable GCC-only solution is fine.
One way is to add a sentinel maximum value to your enum, which you can use to verify that this maximum value is the same as the number of elements in the array.
enum {
ID_FOO = 0,
ID_BAR,
ID_BAZ,
// insert new values here
ID_MAX
}
assert(ID_MAX == (sizeof(arr)/sizeof(arr[0]) - 1));
This is a runtime check; have a look at C compiler asserts - how to implement? for ideas on how to get a compile-time error instead.
you can use X-Macros to keep them in sync, although some may argue about the prettiness of the resulting code.
The idea is to take all the information you need for both structures and put it into a single macro:
entries.inc
ENTRY(ID_FOO, "foo stuff")
ENTRY(ID_BAR, "bar stuff")
ENTRY(ID_BAZ, "baz stuff")
And then later, redefine your macro such that for each structure you need to build, you pull out the appropriate part from your data:
foo.c
/* here define what entry should be for your enums */
#define ENTRY(id, name) id,
enum {
#include "entries.inc"
};
/* and then redefine for the char array and include again */
#undef ENTRY
#define ENTRY(id, name) [id] = name,
char* arr[] = {
#include "entries.inc"
0
};
int main(int argc, char* argv[]) {
/* whatever */
}
Related
How can I ensure COLOR_NAMES is filled to the correct size at compile-time? If a new color is added, say COLOR_4 (and hence N_COLORS is auto incremented), the compiler will then tell me COLOR_NAMES is not filled to size.
Most answers that I found online is for runtime, not compile time.
This is for C-style notation (no STL and other libraries usage).
enum Colors
{
COLOR_1,
COLOR_2,
COLOR_3,
N_COLORS;
};
const char* COLOR_NAMES[N_COLORS] =
{
/* COLOR_1 */ "Color1",
/* COLOR_2 */ "Color2",
/* COLOR_3 */ "Color3"
};
const char* Blah()
{
Colors color;
...
printf("%s blah blah\n", COLOR_NAMES(color));
}
It is standard practice for such cases of arrays and corresponding enums to compare the "enum size member", N_COLORS in your case, against the number of items in the array.
To get the number of items in an array, simply divide the array size with the size of one array member.
Thus:
_Static_assert(sizeof(COLOR_NAMES)/sizeof(*COLOR_NAMES) == N_COLORS,
"Array item missing!");
Edit:
Oh btw for this to be meaningful the array declaration must be const char* COLOR_NAMES[] = otherwise you wouldn't be able to tell if there are missing initializers in the array initialization list.
The ideal would to be able to use sizeof from preprocessor. But we can't because sizeof is evaluated by the compiler.
There are many ways to bypass this but here is quite simple and portable one:
const char* COLOR_NAMES[] = {
/* COLOR_1 */ "Color1",
/* COLOR_2 */ "Color2",
/* COLOR_3 */ "Color3"
};
typedef char CHECK_COLOR_NAMES[sizeof(COLOR_NAMES) / sizeof(COLOR_NAMES[0]) == N_COLORS ? 1 : -1];
If the test fails, you will attempt to define an array with size -1, which will result into a compilation error.
EDIT: Then we use a typedef to avoid to actually create a variable that we'll not use (Lundin's remark)
with constepxr, you can use :
constexpr static const char* COLOR_NAMES[N_COLORS] =
{
/* COLOR_1 */ "Color1",
/* COLOR_2 */ "Color2",
/* COLOR_3 */ "Color3"
};
static_assert(COLOR_NAMES[N_COLORS-1] !=0);
if you want to use local variable, you can use variant
constexpr variant<const char*> COLOR_NAMES[N_COLORS] =
{
/* COLOR_1 */ "Color1",
/* COLOR_2 */ "Color2",
/* COLOR_3 */ "Color3"
};
static_assert(get<0>(COLOR_NAMES[N_COLORS-1]) !=nullptr);
So I'm trying to utilize Enumerated types in C for the first time. So I have an Enumerated "variable?" declared and I also have a struct which has a variable of the Enumerated type(among other things). Finally I have a static array for which there is an element containing each of the enum "types?" in the same order they were declared. I am hoping to use the enum type to act as an index for the array.
So my problem is that I need to somehow relate a char* variable to the enumerated type. If I KNOW that the Char* variable is one of the enum types, is there some way to assert that without having to look at each char to determine which specific enum"option" it is?
Example:
enum example = {abc,def}
struct _strExample {
enum example letters;
....
};
typedef struct _strExample strEx;
static strEx Table[2] = {
{abc,...}
{def,...}
};
//Given char* "abc" , want either example.abc or 0 ( correct index of table)
So given the char* "abc"(does not need to be char*), is there a simple way to get either the correct enum "type?"(abc or def)or the correct index of the table? I know that I could check all the individual chars in the char* and manually determine which enumerated "type?" it is, but I am going to be working with a very large set of enumerated variables and this kind of thing is exactly what I was trying to avoid. any help or advice you guys could give on enumerated types and/or my design would be most appreciated.
Use a an array of strings where the index into the array is the enum value. If the strings are all short, or all about the same length, storing the string in the array makes sense. Otherwise, use a char* pointer.
typedef enum enum_t { plugh, plover, xyzzy, y0 } enum_t;
const char *etable = { "plugh", "plover", "xyxxy", "y0", NULL };
With that, you can convert with a simple search like:
enum_t find_enum(char *sval)
{
enum_t result=plugh; /* value corresponding to etable[0] */
int i=0;
for (i=0; etable[i]!=NULL; ++i, ++result)
if (0==strcmp(sval, etable[i])) return result;
return -1;
}
The enum-to-string converstion is simply etable[e-plugh]. Those allow for a different definition of enum_t where the first meaningful value may not be 0, but the values are sequentially assigned thereafter.
No, you can't lookup any scalar value from a character array. You have to iterate over a set of strings to compare and find the relation to the enum member.
You can use an array of structs
typedef struct { int value; const char * name; } lookup_t;
lookup_t lookup[] = {
{ 1, "One"},
{ 0, NULL} // end tag, alternatively use the _countof(lookup) to get the number of elements
};
and compare your char* with the name member. Then you use the value on match.
Use if :
char *ex = "abc";
strEx strex;
if(!(strcmp("abc",ex))) {
strex.letters = abc;
}
else {
strex.letters = def;
}
In C99 is there an easier way of check if a structure of function pointers is NULL, other than checking each individual pointer?
What I currently have is similar to the following:
typedef struct {
void* (*foo)(int a);
int (*bar)(int a, int b);
} funcs;
void *funcs_dll;
funcs_dll = dlopen("my_funcs_dll.so", RTLD_GLOBAL);
if (funcs_dll == NULL) {
THROW_ERROR;
}
funs.foo = dlsym(funcs_dll, "foo");
funcs.bar = dlsym(funcs_dll, "bar");
if (!funcs.foo || !funcs.bar) {
THROW_ERROR;
}
What I am looking to do is reduce the second if check, so that I do not need to check each individual function. Any suggestions would be helpful.
Not directly, no.
You can't use memcmp() to compare to some constant buffer, since there might be padding inside the structure which will have "random" values. If you can make sure that the size of the structure is exactly the sum of the function pointer fields, you can perhaps go that way.
You can also use a proxy, by i.e. declaring an initial uint32_t member that is a bitset representing which function pointer(s) are valid. Then you can check up to 32 (or 64 with uint64_t) proxy bits in parallel.
If you only want to do this once, my suggestion would be a data-driven approach. Define a table of function names to look for, and process that in a loop, exiting as soon as a dlsym() call fails.
Something like:
const struct {
const char *name;
size_t offset;
} functions[] = {
{ "foo", offsetof(funcs, foo) },
{ "bar", offsetof(funcs, bar) },
};
Data-driven code like this is very powerful, and often very fast.
Make wrapper function for dlsym which will set error flag, if return value is NULL.
I could be going about this all wrong, and it could be that an enum does is not a good way to solve this problem, but I am really not sure where to go with it otherwise.
Basically, I have non-sequential codes that correspond to certain strings. For example,
9 = "Enter"
10 = "Right"
15 = "Left"
17 = "Down"
And so on. I currently have this implemented with a large set of definitions:
#define ENTER_INDEX 0
#define RIGHT_INDEX 1
That is used to index into a char* array:
char* array[] = { "Enter", "Right" };
And when I receive information regarding which code was received, I then print the strings with a huge switch-case.
Any ideas on how to do this more efficiently? Is an enum a good approach?
Sure, you can use an enum, but that won't help you associate the names with the numerical values.
The problem is that you can't declare an enum and a string "in parallel" from the same source code characters, without using trickery such as X macros. Even then you probably won't solve the requirement for different casing which your code shows. Which you might want to avoid, because obfuscation.
The enum would be just:
typedef enum {
ID_ENTER = 9,
ID_RIGHT = 10,
ID_LEFT = 15,
ID_DOWN = 17
} Id;
I would then use C99's fantastic support for explicit indexes in array initializers to declare an array of strings indexed by an Id:
static const char *id_names[] = {
[ID_ENTER] = "Enter",
[ID_RIGHT] = "Right",
/* add more */
};
Note that the above is independent of the order, since each element initializer has an explicit index. This makes it very robust.
You can of course use a macro to cut down on the repetition, but that will make an all-caps string array:
#define DECL_ID(i) [ID_ ## i] = #i
static const char *id_names2[] = {
DECL_ID(ENTER), DECL_ID(RIGHT), /* add more */
};
To implement an enum with specific values for its members can be done by
enum options_en
{
Enter=9,
Right=10,
Left=15,
Down=17,
Default=0;
} ;
then you can declare a variable which can take only values defined in the enumerated type
options_en opt_val = Default;
For exploring more information about your question , refer this link, Found it very useful and is relevent to your question
http://www.cprogramming.com/tutorial/enum.html
A dictionary or hash table can be used. In c++ stl libraries I don't recall the name of the collection but in short y. use dictionaries/hashtables with generics.
So in your case you fill up the dictionary with key value pairs and when your later use the collection you can get a value using your key.
So it gets rid of switch statements and enums and will allow you to map any two types. Here is pseudo code
Value = dictionary[key]
So if key is 0 then the value will be set to Enter based on your example.
In short lookup examples for c++ and dictionary as I am answering from mobile phone and could not direct you to the exact collection name.
You can also create a map during initialization:
#include<stdio.h>
typedef struct { int code; const char *str; } key_info;
key_info keys[] = {
{9, "Enter"}, {10, "Right"}, {15, "Left"}, {-1, NULL}
};
#define MAX_KEY_CODE 15
size_t keymap[MAX_KEY_CODE + 1];
int main ( ) {
size_t i;
for (i = 0; keys[i].str; i++) {
keymap[keys[i].code] = i;
}
printf("%s\n", keys[keymap[10]].str);
return 0;
}
A huge switch is not a bad solution. The question is why do you need an extra array of names. Why don't you return directly string literals from the switch?
char *name(int code) {
switch (code) {
case 9: return("Enter");
case 10: return("Right");
case 15: return("Left");
...
}
}
This question already has answers here:
Easy way to use variables of enum types as string in C?
(20 answers)
Closed 6 years ago.
gcc 4.4.2 c89
I have the following enum:
enum drop_options_e
{
drop_ssm,
drop_snm,
drop_ssb
};
I am just wondering that is the best way to get the string representation value from the enum.
So basically, instead of returning the value of 0 for drop_ssm, I could get the 'drop_ssm' instead.
Many thanks for any advice,
One way is to do like this:
enum drop_options_e
{
drop_ssm = 0,
drop_snm ,
drop_ssb ,
LAST_ENTRY /* Should be last entry */
};
const char* drop_options_s[LAST_ENTRY] = {"drop_ssm", "drop_snm", "drop_ssb"};
when you want a string representation of an enum you can drop_options_s[enum];
Using X-Macro technique:
file items:
ITEM(drop_ssm)
ITEM(drop_snm)
ITEM(drop_ssb)
source:
#define ITEM(A) A,
enum drop_options_e
{
#include "items"
last
};
#undef ITEMS
#define ITEM(A) #A,
char item_names[] = {
#include "items"
NULL};
So now item_names[drop_ssm] will give you text string "drop_ssm"
C has no support for that. You will have to have a switch or equivalent somewhere.
If you have a compiler that supports C99's designated initialisers, you can improve upon Naveen's answer:
enum drop_options_e
{
drop_ssm,
drop_snm,
drop_ssb
};
#define ENUM_TO_S(e) [e] = #e
const char *drop_options_s[] = {
ENUM_TO_S(drop_ssm),
ENUM_TO_S(drop_snm),
ENUM_TO_S(drop_ssb)
};
(With this method, you don't have to worry about the array initialisers being in the same order as the enum values).
There's nothing out of the box. You can do some very interesting things with macros and Boost.Preprocessor, but it's quite involved, and I'm not sure how well it would work in C; I've done things in C++ that let me write, e.g.:
ENUM(
ColorComponent,
(red)
(green)
(blue)
(alpha)
);
// ...
ColorComponent cc = ColorComponent_red;
std::cout << "Color: " << toString(cc) << "\n";
The best way I have see to handle this is to create a translation array. Something like:
struct {
enum drop_options_e value;
char *string;
} TranslationArray[] = {
drop_ssm, "drop_ssm",
drop_snm, "drop_snm",
drop_ssb, "drop_ssb",
};
This can be problematic if you're enum is quite large.
I've so liked all answers here! During trying them I've found something very short and nice with BOOST_PP_STRINGIZE macro from boost:
//Define the enum you need
typedef enum
{
INTEGER = 0,
STRING = 1,
BOOLEAN = 2,
}eValueType;
// Then in code use BOOST_PP_STRINGIZE, for example:
char* valueTypeStr = BOOST_PP_STRINGIZE(INTEGER);