Is using enums safe in all compilers? - c

In a discussion, a colleague told me that he never uses enum because he experienced that some C-compilers don't cope with the enum statement correctly.
He couldn't remember which compiler exactly had problems but among the problems, there were errors when doing something like
enum my_enum{
my_enum_first = 5;
my_enum_second = 10;
};
i.e. initializing enum values instead of letting the compiler do the automatic assignment. Another one was that the compiler decides for itself how big the enum is and therefore you could have unpredictable behavior for sizeof my_enum when compiling your code under various platforms.
To get around that, he told me to better use #defines to define the constant elements. But especially for using doxygen it's quite handy to have an enum (e.g. as function parameter) because in the generated documentation, you could simply click on my_enum and directly jump to the description of my_enum.
Another example would be code completion, where your IDE tells you what you could specify as valid parameters for functions. I know that – as long as you're compiling the code as C-code – that there's no type-safety (i.e. I could also specify 5 instead of my_enum_first), so the use of an enum seems to be a more cosmetic thing.
The question is: do you know any compilers that have limitations regarding the usage of enum?
Edit 1:
Regarding the environment: we are developing for various embedded platforms, so there could also be a compiler for some obscure micro-controller...
Edit 2:
He could tell me that the KEIL C51 compiler didn't play well with enums. Are there any experiences with current versions of the C51 compiler?

Compilers are free to choose the size of an enum based on its range of possible values. This only really becomes an issue if you're exposing enums in your API, and users of your code may be using a different compiler or build options.
In this case, confusion can be caused by the calling code passing in a 16-bit value, for example, and the receiving code expecting it to be 32 bits. If the top 16 bits of the passed-in value are left uninitialized, then bad things will happen.
You can work around this kind of issue by including a dummy entry in your enum to enforce a minimum size.
For example:
typedef enum {
FirstValue = 12,
SecondValue = 25,
DummyValue = 65536 // force enum to be greater than 16 bits
} MyEnum;

I'm pretty sure that a compiler that doesn't play nice with enum is an invalid compiler - enum is specified in the standard, so a failure to implement it means the compiler shouldn't technically be used to compile C (For the record, the scope of enumeration types is discussed in 6.2.1 and defined as a type in 6.2.5 (of C99), so one would assume that it's a valid part of the standard from thereon in)!
So no, I don't know of any such compilers.

Related

Combining constant suffixes and portable data types

This seems like a stupidish question that will cost me some reputation scores, but I nonetheless eager to receive feedbacks on this one-
Almost all projects I was working on (embedded systems), either proprietary drivers or 3rd party libraries contained both concepts:
First concept is the use of UL suffix (also UUL) in constant definitions, for example:
#define BIT_0 0x1UL
#define BIT_1 0x2UL
Second concept is using the portable types for variable declarations and functions parameters, for example:
uint32_t func (uint32_t input1);
And suddenly it hit me, though its almost a second nature for me and my colleagues to add UL (and ULL) suffixes to constants, and use portable types for variables, the combination of both (for example if such a constant will be assigned to, manipulated with, or compared to portable variable) is actually wrong as the first concept is non-portable (long can vary in length on different systems) and the second one is.
My question here is this - am I wrong with my enlightenment? is the combination of both concepts actually makes good programming? or am I right and the fact that we use both concept is a result of lack of knowledge?
No, you are not wrong. The suffixes that hardcode "abstract" types like unsigned long are not very compatible with using the more concrete types with specified widths.
Sometimes people simply know the mapping, which can make it correct anyway, but it's not as portable or clean.
There are macros you can use for literals, see <stdint.h>:
The macro INTN_C shall expand to an integer constant expression corresponding to the type int_leastN_t (so e.g. INT32_C(4711) generates a constant compatible with int32_t).
The same for UINTN_C().
You are right, it might create issues on some systems.
I would use the following define for compatibility:
#define BIT_0 (uint32_t)1U
EDIT: If one wants to be fully compatible, the defines should be tossed away
uint32_t x = (uint32_t)1U << n;
The person reading your code might know the C language, but might not know the magic macros
EDIT2 : Similarly, one can also use the standard INTN_C format:
#define BIT_0 UINT32_C(1U)
or
uint32_t x = UINT32_C(1) << n;

Is this enumeration construct and assignment allowed?

Will this compile and work as meant under Linux GCC ?
In the LoRa Gateway Stack hosted at Github I found the following construct in loragw_hal.h
enum lgw_radio_type_e {
LGW_RADIO_TYPE_NONE,
LGW_RADIO_TYPE_SX1255,
LGW_RADIO_TYPE_SX1257
};
#define LGW_RF_CHAIN_NB 2 /* number of RF chains */
and then in loragw_hal.c
static enum lgw_radio_type_e rf_radio_type[LGW_RF_CHAIN_NB];
edit: the array is not initialized at any place in the code
and then in the function
setup_sx125x(uint8_t rf_chain, uint32_t freq_hz)
the following switch statement is used to select the rf chain according to the rf_chain argument
switch (rf_radio_type[rf_chain]) {
case LGW_RADIO_TYPE_SX1255:
// some code
break;
case LGW_RADIO_TYPE_SX1257:
// some code
break;
default:
DEBUG_PRINTF("ERROR: UNEXPECTED VALUE %d FOR RADIO TYPE\n",
rf_radio_type[rf_chain]);
break;
}
rf_chain argument is set to 1, when the function is called, and it selects the default Error 'unexpected rf chain' of course.
The copyright holder Semtech Inc. support, points always to this code, if you have any problems with their product, as reference.
But I have the feeling that this code wouldn't run anyway without any modifications.
So my question to the forum here is, aside from that this construct above makes not really sense, is that not a faulty construct anyway ?
Will this compile and work as meant under Linux GCC ?
I try to use this code under GCC ARM and it does NOT work as it seems to be planned.
You seem to be trying to draw attention to this:
enum lgw_radio_type_e {
LGW_RADIO_TYPE_NONE,
LGW_RADIO_TYPE_SX1255,
LGW_RADIO_TYPE_SX1257
};
#define LGW_RF_CHAIN_NB 2 /* number of RF chains */
[...]
static enum lgw_radio_type_e rf_radio_type[LGW_RF_CHAIN_NB];
[...] the array is not initialized at any place in the code
It is not a particular problem that the array is not explicitly initialized. File-scope variables (and static block-scope variables) are subject to default initialization if no explicit initializer is provided. In this case, the array declaration is equivalent to
static enum lgw_radio_type_e rf_radio_type[2] = {
LGW_RADIO_TYPE_NONE, LGW_RADIO_TYPE_NONE
};
That seems to be quite sensible in itself.
You go on to say,
[...] when the function is called, and it selects the default Error 'unexpected rf chain' of course.
I don't see any reason to expect a different case to be selected, but neither do I see any justification for assuming that a different one would not be selected. Nor is it clear under what circumstances the switch itself is executed at all.
One would normally expect one or both elements of rf_radio_type to be set during driver initialization if in fact the corresponding hardware is present. If the overall code (not just the parts you've presented) is correct, then probably it will not execute the presented switch when rf_radio_type[rf_chain] has a value different from both LGW_RADIO_TYPE_SX1255 and LGW_RADIO_TYPE_SX1257. On the other hand, printing the error message is essentially harmless in itself; if the driver prints it then that may be merely a quality-of-implementation issue, not a functional flaw.
So my question to the forum here is, aside from that this construct
above makes not really sense, is that not a faulty construct anyway ?
No, it isn't. And as far as I can tell, all constructs presented make as much sense as can be expected when taken out of context as they have been.
Will this compile and work as meant under Linux GCC ?
You have presented several individually valid C fragments, but they do not together constitute a valid translation unit. It is possible to form a complete, valid translation unit containing all those fragments that will compile successfully and do absolutely anything. The fragments will not inherently interfere with compilation, nor necessarily cause malfunction.
I try to use this code under GCC ARM and it does NOT work as it seems to be planned.
I find your apparent confidence in your assessment of the intended behavior of the overall code to be a bit optimistic.
edit: the array is not initialized at any place in the code
As pointed out in another answer, variables with static storage duration are required by the C standard to get implicitly initialized to zero if the programmer didn't set them explicitly. So this is code fine as far as the C standard is concerned.
However, writing code relying on initialization of static storage duration variables in .bss is recognized as bad practice in embedded systems programming. This is because the code that does the copy-down of .data and zero initialization of .bss is often omitted on embedded systems, as a very common non-standard practice in order to speed up program start-up.
Such a non-standard option is usually called "minimal/compact/fast start-up" or similar in the compiler options. If you have such an option enabled - which is quite common - the code won't work.
Good practice is to initialize such variables later on in "run-time" instead, before they are used for the first time.
Summary: the code is sloppily written, since the intention here is to provide portable code across many different microcontroller platforms, rather than to provide code for some PC. I would guess it was written by some kind of PC programmer, as is often the case for these protocol stacks.

difference between #define and enum{} in C [duplicate]

What's the difference between using a define statement and an enum statement in C/C++ (and is there any difference when using them with either C or C++)?
For example, when should one use
enum {BUFFER = 1234};
over
#define BUFFER 1234
enum defines a syntactical element.
#define is a pre-preprocessor directive, executed before the compiler sees the code, and therefore is not a language element of C itself.
Generally enums are preferred as they are type-safe and more easily discoverable. Defines are harder to locate and can have complex behavior, for example one piece of code can redefine a #define made by another. This can be hard to track down.
#define statements are handled by the pre-processor before the compiler gets to see the code so it's basically a text substitution (it's actually a little more intelligent with the use of parameters and such).
Enumerations are part of the C language itself and have the following advantages.
1/ They may have type and the compiler can type-check them.
2/ Since they are available to the compiler, symbol information on them can be passed through to the debugger, making debugging easier.
Enums are generally prefered over #define wherever it makes sense to use an enum:
Debuggers can show you the symbolic name of an enums value ("openType: OpenExisting", rather than "openType: 2"
You get a bit more protection from name clashes, but this isn't as bad as it was (most compilers warn about re#defineition.
The biggest difference is that you can use enums as types:
// Yeah, dumb example
enum OpenType {
OpenExisting,
OpenOrCreate,
Truncate
};
void OpenFile(const char* filename, OpenType openType, int bufferSize);
This gives you type-checking of parameters (you can't mix up openType and bufferSize as easily), and makes it easy to find what values are valid, making your interfaces much easier to use. Some IDEs can even give you intellisense code completion!
Define is a preprocessor command, it's just like doing "replace all" in your editor, it can replace a string with another and then compile the result.
Enum is a special case of type, for example, if you write:
enum ERROR_TYPES
{
REGULAR_ERR =1,
OK =0
}
there exists a new type called ERROR_TYPES.
It is true that REGULAR_ERR yields to 1 but casting from this type to int should produce a casting warning (if you configure your compiler to high verbosity).
Summary:
they are both alike, but when using enum you profit the type checking and by using defines you simply replace code strings.
It's always better to use an enum if possible. Using an enum gives the compiler more information about your source code, a preprocessor define is never seen by the compiler and thus carries less information.
For implementing e.g. a bunch of modes, using an enum makes it possible for the compiler to catch missing case-statements in a switch, for instance.
enum can group multiple elements in one category:
enum fruits{ apple=1234, orange=12345};
while #define can only create unrelated constants:
#define apple 1234
#define orange 12345
#define is a preprocessor command, enum is in the C or C++ language.
It is always better to use enums over #define for this kind of cases. One thing is type safety. Another one is that when you have a sequence of values you only have to give the beginning of the sequence in the enum, the other values get consecutive values.
enum {
ONE = 1,
TWO,
THREE,
FOUR
};
instead of
#define ONE 1
#define TWO 2
#define THREE 3
#define FOUR 4
As a side-note, there is still some cases where you may have to use #define (typically for some kind of macros, if you need to be able to construct an identifier that contains the constant), but that's kind of macro black magic, and very very rare to be the way to go. If you go to these extremities you probably should use a C++ template (but if you're stuck with C...).
If you only want this single constant (say for buffersize) then I would not use an enum, but a define. I would use enums for stuff like return values (that mean different error conditions) and wherever we need to distinguish different "types" or "cases". In that case we can use an enum to create a new type we can use in function prototypes etc., and then the compiler can sanity check that code better.
Besides all the thing already written, one said but not shown and is instead interesting. E.g.
enum action { DO_JUMP, DO_TURNL, DO_TURNR, DO_STOP };
//...
void do_action( enum action anAction, info_t x );
Considering action as a type makes thing clearer. Using define, you would have written
void do_action(int anAction, info_t x);
For integral constant values I've come to prefer enum over #define. There seem to be no disadvantages to using enum (discounting the miniscule disadvantage of a bit more typing), but you have the advantage that enum can be scoped, while #define identifiers have global scope that tromps everything.
Using #define isn't usually a problem, but since there are no drawbacks to enum, I go with that.
In C++ I also generally prefer enum to const int even though in C++ a const int can be used in place of a literal integer value (unlike in C) because enum is portable to C (which I still work in a lot) .
If you have a group of constants (like "Days of the Week") enums would be preferable, because it shows that they are grouped; and, as Jason said, they are type-safe. If it's a global constant (like version number), that's more what you'd use a #define for; although this is the subject of a lot of debate.
In addition to the good points listed above, you can limit the scope of enums to a class, struct or namespace. Personally, I like to have the minimum number of relevent symbols in scope at any one time which is another reason for using enums rather than #defines.
Another advantage of an enum over a list of defines is that compilers (gcc at least) can generate a warning when not all values are checked in a switch statement. For example:
enum {
STATE_ONE,
STATE_TWO,
STATE_THREE
};
...
switch (state) {
case STATE_ONE:
handle_state_one();
break;
case STATE_TWO:
handle_state_two();
break;
};
In the previous code, the compiler is able to generate a warning that not all values of the enum are handled in the switch. If the states were done as #define's, this would not be the case.
enums are more used for enumerating some kind of set, like days in a week. If you need just one constant number, const int (or double etc.) would be definetly better than enum. I personally do not like #define (at least not for the definition of some constants) because it does not give me type safety, but you can of course use it if it suits you better.
Creating an enum creates not only literals but also the type that groups these literals: This adds semantic to your code that the compiler is able to check.
Moreover, when using a debugger, you have access to the values of enum literals. This is not always the case with #define.
While several answers above recommend to use enum for various reasons, I'd like to point out that using defines has an actual advantage when developing interfaces. You can introduce new options and you can let software use them conditionally.
For example:
#define OPT_X1 1 /* introduced in version 1 */
#define OPT_X2 2 /* introduced in version 2 */
Then software which can be compiled with either version it can do
#ifdef OPT_X2
int flags = OPT_X2;
#else
int flags = 0;
#endif
While on an enumeration this isn't possible without a run-time feature detection mechanism.
Enum:
1. Generally used for multiple values
2. In enum there are two thing one is name and another is value of name name must be distinguished but value can be same.If we not define value then first value of enum name is 0 second value is 1,and so on, unless explicitly value are specified.
3. They may have type and compiler can type check them
4. Make debugging easy
5. We can limit scope of it up to a class.
Define:
1. When we have to define only one value
2. It generally replace one string to another string.
3. It scope is global we cannot limit its scope
Overall we have to use enum
There is little difference. The C Standard says that enumerations have integral type and that enumeration constants are of type int, so both may be freely intermixed with other integral types, without errors. (If, on the other hand, such intermixing were disallowed without explicit casts, judicious use of enumerations could catch certain programming errors.)
Some advantages of enumerations are that the numeric values are automatically assigned, that a debugger may be able to display the symbolic values when enumeration variables are examined, and that they obey block scope. (A compiler may also generate nonfatal warnings when enumerations are indiscriminately mixed, since doing so can still be considered bad style even though it is not strictly illegal.) A disadvantage is that the programmer has little control over those nonfatal warnings; some programmers also resent not having control over the sizes of enumeration variables.

#define or enum? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Why use enum when #define is just as efficient?
When programming in C, is it better practice to use #define statements or enums for states in a state machine?
Technically it doesn't matter. The compiler will most likely even create identical machine code for either case, but an enumeration has three advantages:
Using the right compiler+debugger combination, the debugger will print enumeration variables by their enumeration name and not by their number. So "StateBlahBlup" reads much nicer than "41", doesn't it?
You don't have explicitly give every state a number, the compiler does the numbering for you if you let it. Let's assume you have already 20 states and you want to add a new state in the middle, in case of defines, you have to do all renumbering on your own. In case of enumeration, you can just add the state and the compiler will renumber all states below this new state for you.
You can tell the compiler to warn you if a switch statement does not handle all the possible enum values, e.g. because you forgot to handle some values or because the enum was extended but you forgot to also update the switch statements handling enum values (it will not warn if there's a default case though, as all values not handled explicitly end up in the default case).
Since the states are related elements I think is better to have an enum defining them.
There's no definitive answer. enum offers you scoping and automatic value assignment, but does not give any control over the constant type (always signed int). #define ignores scoping, but allows you to use better typing facilities: lets you choose the constant type (either by using suffixes or by including an explicit cast into the definition).
So, choose for yourself what is more important to you. For a state machine, enum might be a better choice, unless you have a good reason to control the type.
I prefer enum. They are more compact and are 'safer'. You can also imply order in an enum, which might be helpful in a state machine. #defines should be avoided if possible, since they will overwrite all occurrences in source, which can lead to some unintended actions which are difficult to debug.
If enum is supported by your compiler, then that would be preferred. Failing that, by all means, use #define. All C++ compilers and modern C compilers should support enum, but older compilers (particularly ones targeting embedded platforms) may not support enum.
If you must use #define make sure to define your constants with parentheses, to avoid preprocessor errors:
#define RED_STATE (1)
#define YELLOW_STATE (2)
#define GREEN_STATE (3)
#define directives can have lots of unintended consequences and don't follow common scoping rules. Use enums when you have related data.
More information: http://www.embedded.com/columns/programmingpointers/9900402?_requestid=341945 [C++ material, but still marginally relevant]
You can do this trick to make compiler check the type of #define value.
#define VALUE_NAME ((TYPE_NAME) 12)
However the real problem of #define is it can be redefined in application code. (Of course compiler will warn you about it.)
enum is great when you have exclusive options, but you can't use them to define bitfield flags, like this:
#define SQ_DEFAULT 0x0
#define SQ_WITH_RED 0x1
#define SQ_WITH_BLUE 0x2
void paint_square(int flags);
Then you can paint red-blue square with:
paint_square(SQ_WITH_RED | SQ_WITH_BLUE);
...which you can't with enum.
You can use whatever you want and like.
Still as everyone is saying I would also like add up me as voting for Enums.
Enums should always be preferred if you are using related data as in case of a State Machine, you can define order in enums also that will help in implementing the State Machine.
Further enums will keep your program safe as all enums will be of its type only so they will avoid any possible confusions too.
#define should not be used in case of a state machine or related data. Anyway thats my suggestion, but there is no hard and fast rule.
Also I would like to add up one more point that enums will add more readability and understandability to your code if used in future or or if read by someone else. It is an important point when you are having a very large program and there are a lot of #defines in the program other than you are using for your State Machine.

Shall I prefer constants over defines?

In C, shall I prefer constants over defines? I've reading a lot of code lately, and all of the examples make heavy use of defines.
No, in general you should not use const-qualified objects in C to create names constants. In order to create a named constant in C you should use either macros (#define) or enums. In fact, C language has no constants, in the sense that you seem to imply. (C is significantly different from C++ in this regard)
In C language the notions of constant and constant expression are defined very differently from C++. In C constant means a literal value, like 123. Here are some examples of constants in C
123
34.58
'x'
Constants in C can be used to build constant expressions. However, since const-qualified objects of any type are not a constants in C, they cannot be used in constant expressions, and, consequently, you cannot use const-qualified objects where constant expressions are required.
For example, the following is not a constant
const int C = 123; /* C is not a constant!!! */
and since the above C is not a constant, it cannot be used to declare an array type in file scope
typedef int TArray[C]; /* ERROR: constant expression required */
It cannot be used as a case label
switch (i) {
case C: ; /* ERROR: constant expression required */
}
It cannot be used as bit-field width
struct S {
int f : C; /* ERROR: constant expression required */
};
It cannot be used as an initializer for an object with static storage duration
static int i = C; /* ERROR: constant expression required */
It cannot be used as a enum initializer
enum {
E = C /* ERROR: constant expression required */
};
i.e it cannot be used anywhere where a constant is required.
This might seem counter-intuitive, but this is how C the language is defined.
This is why you see these numerous #define-s in the code you are working with. Again, in C language const-qualified object have very limited use. They are basically completely useless as "constants", which is why in C language you are basically forced to use #define or enums to declare true constants.
Of course, in situations when a const-qualified object works for you, i.e. it does what you want it to do, it is indeed superior to macros in many ways, since it is scoped and typed. You should probably prefer such objects where applicable, however in general case you'll have to take into account the above limitations.
Constants should be preferred over defines. There are several advantages:
Type safety. While C is a weakly typed languaged, using a define loses all of the type safety, which will allow the compiler to pick up problems for you.
Ease of debugging. You can change the value of constants through the debugger, while defines are automatically changed in the code by the pre-processor to the actual value, meaning that if you want to change the value for test/debugging purposes, you need to re-compile.
Maybe I have been using them wrong but, at least in gcc, you can't use constants in case statements.
const int A=12;
switch (argc) {
case A:
break;
}
Though this question is specific to C, I guess it is good to know this:
#include<stdio.h>
int main() {
const int CON = 123;
int* A = &CON;
(*A)++;
printf("%d\n", CON); // 124 in C
}
works in C, but not in C++
One of the reasons to use #define is to avoid such things to mess up your code, specially it is a mix of C and C++.
A lot of people here are giving you "C++ style" advice. Some even say the C++ arguments apply to C. That may be a fair point. (Whether it is or not feels kind of subjective.) The people who say const sometimes means something different in the two languages are also correct.
But these are mostly minor points and personally, I think in truth there is relatively minor consequence to going either way. It's a matter of style, and I think different groups of people will give you different answers.
In terms of common usage, historical usage, and most common style, in C, it's a lot more typical to see #define. Using C++isms in C code can come off as strange to a certain narrow segment of C coders. (Including me, so that's where my biases lie.)
But I'm surprised no one has suggested a middle ground solution, that "feels right" in both languages: if it fits into a group of integer constants, use an enum.
define can be used for many purposes(very loose) and should be avoided if you can substitute that with const, which define a variable and you can do a lot more with it.
In cases like below, define has to be used
directive switch
substitution to your source line
code macros
An example where you have to use define over const is when you have version number say 3 and you want version 4 to include some methods that is not available in version 3
#define VERSION 4
...
#if VERSION==4
................
#endif
Defines have been part of the language longer than constants, so a lot of older code will use them because defines where the only way to get the job done when the code was written. For more recent code it may be simply a matter of programmer habit.
Constants have a type as well as a value, so they would be preferred when it makes sense for your value to have a type, but not when it is typeless (or polymorphic).
If it's something that isn't determined programmatically, I use #define. For example, if I want all of my UI objects to have the same space between them, I might use #define kGUISpace 20.
Apart from the excellent reasons given by AndreyT for using DEFINES rather than constants in "C" code there is another more pragmatic reason for using DEFINES.
DEFINES are easy define and use from (.h) header files, which is where any experienced C coder would expect to find constants defined. Defining consts in header files is not quite so easy -- its more code to avoid duplicate definitions etc.
Also the "typesafe" arguments are moot most compilers will pick up glaring errors suchh as assing a string to and int, or, will "do the right thing" on a slight mismatch such as assigning an integer to a float.
Macros (defines) can be used by the pre-processor and at compile time, constants cannot.
You can do compile-time checks to make sure a macro is within a valid range (and #error or #fatal if it isn't). You can use default values for a macro if it hasn't already been defined. You can use a macro in the size of an array.
A compiler can optimize with macros better than it can with constants:
const int SIZE_A = 15;
#define SIZE_B 15
for (i = 0; i < SIZE_A + 1; ++i); // if not optimized may load A and add 1 on each pass
for (i = 0; i < SIZE_B + 1; ++i); // compiler will replace "SIZE_B + 1" with 16
Most of my work is with embedded processors that don't have amazing optimizing compilers. Maybe gcc will treat SIZE_A like a macro at some optimization level.

Resources