This question already has answers here:
Why use enum when #define is just as efficient? [duplicate]
(4 answers)
Closed 1 year ago.
I am a bit confused by what for and where enum is good? What are the benefits of using enum against defining global variables (constants) or macros? For instance in this code:
#include<stdio.h>
enum bool {false, true};
int main()
{
enum bool b = 100;
printf("%d", b);
return 0;
}
I can assign even any integer value to b and every thing works fine, so why not doing
int false = 0, true = 1;
or
#define false 0
#define true 1
in the global scope? Can some one explain where and why are enums useful and should be preferred to use?
There are many advantages to using enum over #define macros:
Advantage and disadvantages of #define vs. constants?
The use of an enumeration constant (enum) has many advantages over
using the traditional symbolic constant style of #define. These
advantages include a lower maintenance requirement, improved program
readability, and better debugging capability.
I would also encourage you to use bool (and <stdbool.h>) instead of an enum for true/false.
Related
This question already has answers here:
Are typedef and #define the same in c?
(11 answers)
Closed 6 years ago.
I have come across the following problem, and I could not find any specific explanations as to: Why does C bother to provide type definitions ? Isn't defining BOOL macro just as good as defining Bool type using typedef?
For example, #define directive can be used to create a macro that could be used as a Boolean type:
#define Bool int
There's another way to set up a Boolean type, using a feature known as type definition.
typedef int Bool;
Why is the last method preferred? What are the advantages?
There are two important differences between type definitions and macro definitions.
Type definitions are more powerful than macro definitions. In particular, array and pointer types can't be defined as macros. Suppose that we try to use a macro to define a "pointer to integer" type:
#define PTR_TO_INT int *
The declaration
PTR_TO_INT p, q, r
will become
int * p, q, r
after preprocessing. Unfortunately, only p is a pointer; q and r are ordinary integer variables. Type definitions don't have this problem.
Second, typedef names are subject to the same scope rules as variables; a typedef name defined inside a function body wouldn't be recognized outside the function. Macro names, on the other hand, are replaced by the preprocessor wherever they appear.
Apart from the above mentioned reasons, one more thing, a MACRO can be undefined and redefined, but not a typedef. So, from one perspective, a typedef is more definitive.
For example
#define MAX 5
//some use of MAX
#undef MAX
#define MAX 10
// some more use of MAX
is perfectly valid, but an attempt to do something like
typedef int into;
///something....
typedef char into;
is invalid, as the "type" is already defined previously.
So, typedef, which creates an alias to a "type", is considered much more consistent, in that regard.
I am little bit confused. In our production environment, there are few macros already defined. These macros used to return some value. Now our requirement is to prepare some lookup based on these Macros' value. I have created char* array and defined some string at appropriate index. But my manger asked me to convert these macros to enum types and then do lookup. How to implement this using enum? What is the advantage of that? These macros are being used in many different files. Do I have to change anything if I defined enum type?
Thanks in advance !
Sample code:
#define macro_1 1
#define macro_2 2
#define macro_3 3
#define macro_4 4
Lookup:
const char* lookup[] = {.....};
How to implement this using enum?
I suppose your manager asked you to map the macros to enum type. You can simply define an enum type, as long the macros all have integer value, and the enum values don't use the same names as macros.
What is the advantage of that?
Macros are generally not encouraged as they are replaced by value before entering the compiler, it can be error prone compared to using enum types that are checked and managed by compiler.
These macros are being used in many different files. Do I have to change anything if I defined enum type?
Unfortunately yes. But if your macros are isolated in a centeral header file, you can work around by renaming the macros and naming the original names to enum value.
You may find this article useful. http://www.cs.utah.edu/~germain/PPS/Topics/C_Language/enumerated_types.html
Some codes
#include <stdio.h>
#define old_macro_1 1
#define old_macro_2 2
#define old_macro_3 3
enum MacroValues {
macro_1 = old_macro_1,
macro_2 = old_macro_2,
macro_3 = old_macro_3
};
void test_macros(void)
{
const char* lookup[] = {"M0", "M1", "M2", "M3"};
// use an enum variable directly
printf("enum MacrosValues %d\n", macro_1);
// define an enum variable to use as index
enum MacroValues m1 = macro_2;
printf("lookup[%d] = %s\n", m1, lookup[m1]);
}
int main(void)
{
test_macros();
return 0;
}
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 6 years ago.
Improve this question
Why is there no increment operator for enums in C? Even if the corresponding integer values are user-defined it does make perfectly sense to me to iterate with ++ to the next member.
To make it more clear
typedef enum myenum t_myEnum;
enum myenum {
eMember1,
eMember2
}
t_myEnum bla = eMember1;
Now I ask what is the reason against bla++ yields eMember2.
User defined assignments to integers values like
enum myenum {
eMember1 = 0,
eMember2 = 10
}
shouldn't be an obstacle in my opinion.
I am sure it is a drawback of C and C++.
Initially enumerations are considered as sets of integer constants as an alternative for the directive #define. Thus an enumeration in C is a common name for a set of such constants. They were made as simple as possible.:)
There was made a step ahead in C++ and enumerators started to have types of their enumerations. Also you can overload operators ++ for enumerations though I agree with you that it would be better that these operators would be built-in.
For example enumerations could be implemented a similar way as std::initializer_list in C++.
So in my opinion there are only historical reasons for the absence of these operators.
An other drawback is impossibility to get the number of enumerators defined in an enumeration.
I would guess there is no such operator since the work-around is so trivial:
typedef enum
{
eMember1 = 0,
eMember2 = 10
} myenum;
const myenum TABLE [] =
{
eMember1,
eMember2
};
for(size_t i=0; i<sizeof(TABLE)/sizeof(*TABLE); i++)
{
do_something_with(TABLE[i]);
}
Similarly, you could use a const myenum* as iterator.
Another reason why such an operator doesn't exist might be that it doesn't make much sense. Lets pretend there was one, what do you think this code would do?
myenum e = eMember2;
e++;
And what would code like eMember1+1 mean? Value 1 or value 10? Again, there's no consistent logic to it.
Nothing in the C Standard prevent incrementing variables of enum types.
In your example, the typedef is incorrect because you have a forward reference to an enum type, but the following code demonstrates what I think your question is about:
#include <stdio.h>
typedef enum myenum {
eMember1,
eMember2,
} t_myEnum;
int main(void) {
t_myEnum bla = eMember1;
printf("bla=%d\n", bla);
printf("bla++=%d\n", bla++);
printf("bla=%d\n", bla);
return 0;
}
Output:
bla=0
bla++=0
bla=1
Of course the value of bla is just incremented by 1, it may correspond to another enumeration value or not, depending on the actual values of the enumeration values in the enum type.
There is no way to enumerate the defined values of a given enum type.
This question already has answers here:
"static const" vs "#define" vs "enum"
(17 answers)
Why would someone use #define to define constants?
(9 answers)
Closed 8 years ago.
I would like to understand the difference between defining a constant variable as follows:
const int ONE = 1;
and using a preprocessor directive:
#define ONE (1)
I know that in the second case "1" gets in some sense hardcoded and the compiler does not even see the variable ONE, but I am not sure about the first case. The fact of declaring the variable as constant just prevents from accidentally change its value, or does the compiler catch the opportunity to do some optimization? Is there any significant benefit of one approach over the other?
In C, const int c; means that c can't be modified during the run of program. However, c is not a constant during compile time and can not be used in constant expressions. So for example the program:
const int MAX = 10;
int a[MAX];
does not compile, while:
#define MAX 10
int a[MAX];
does.
In C++, const variables are true compile-time constants, so there may be less reasons to use #define for it. An example where #define is necessary is when you need to use the constant in an #if directive.
In general, is it better to define some specific parameters (e.g. (char *) UserIPaddr="192.168.0.5" , (int) MAX_BUF=1024) by #define or constant char */ int?
I read some threads say that it is better not to use #define when it is possible. However, I see quite common usage of #define on open source codes one example from a source code:
#define IEEE80211_WLAN_HDR_LEN 24
a_uint8_t *iv = NULL;
a_uint16_t tmp;
a_uint16_t offset = IEEE80211_WLAN_HDR_LEN;
#define could be avoided to use there, but I wonder why it was preferred to use #define on that case for example. How should I decide when to use #define or not?
In C const declarations do not produce constant expressions, So if you need to have a constant expression its not possible using const, the traditional and more commonly used way to do so is using # define.
For example const int cannot be used in:
a case label or
as a bit-field width or
as array size in a non-VLA array declaration (pre C99 days)
There are few reasons to use #define. There is little it accomplishes that a static const or enum cannot.
As Alok Save mentions, static const int cannot produce an integral constant expression in C (I'm not double checking the C standard; it isn't the case in C++ though). But enum can do that. However enum in pure C does not grow to accommodate values larger than INT_MAX. So if you need a long value to use as an array bound or case label, #define is your friend. Or consider switching to using the C subset of C++, which doesn't have such restrictions.
My rule of thumb is to not use #define unless the symbol must be a compile-time constant. With this in mind, I personally would not have used #define in your example.
To take a different example from the same source file:
#define CRYPTO_KEY_TYPE_AES 2
...
switch (keytype) {
case CRYPTO_KEY_TYPE_AES:
Here, CRYPTO_KEY_TYPE_AES must be a constant expression, and thus using a constant variable would not do.