The importance of c enumeration (typedef enum) [duplicate]
Matthew Harrington
I recently saw this in an answer that was posted for me:
typedef enum
{ NO_OP, ADDITION,
} operator_t;
int main()
{ operator_t operator = NO_OP;
}What is typedef enum and why should we use it? I googled and found the following:
Right now it sounds slightly too technical for me so I don't think I understand what is going on or why anyone would use that.
Bonus (optional): What type of variable is the operator_t?
6 Answers
It's definitely not "too technical".
The basic reason to have "enums" is to avoid "magic numbers":
Let's say you have three "states": STOP, CAUTION and GO. How do you represent them in your program?
One way is to use the string literals "STOP", "CAUTION" and "GO". But that has a lot of problems - including the fact that you can't use them in a C "switch/case" block.
Another way is to Map" them to the integer values "0", "1" and "2". This has a lot of benefits. But seeing "STOP" in your code is a lot more meaningful than seeing a "0". Using "0" in your code like that is an example of a "magic number". Magic numbers are Bad: you want to use a "meaningful name" instead.
Before enums were introduced in the language, C programmers used macros:
#define STOP 0 #define CAUTION 1 #define GO 2A better, cleaner approach in modern C/C++ is to use an enum instead:
enum traffic_light_states { STOP, CAUTION, GO
}; Using a "typedef" just simplifies declaring a variable of this type:
typedef enum { STOP, CAUTION, GO
} traffic_light_states_t ; 3 typedef is used to define an alternative name for an existing type. The enum could have declared like this:
enum operator_t
{ NO_OP, ADDITION,
};and then you could declare a variable of this type like so:
enum operator_t x = NO_OP;This is kind of verbose so you would use typedef to define a shorter alias for this type:
typedef enum operator_t operator_t;This defines operator_t to mean the type enum operator_t allowing you to initialize a variable like so:
operator_t x = NO_OP;This syntax:
typedef enum
{ NO_OP, ADDITION,
} operator_t;does the whole process in one step, so it defines an (untagged or tagless) enum type and gives it the alias operator_t.
Bonus: operator_t is an enum data type; read more about it here:
What is typedef enum and why should we use it?
There are two different things going on there: a typedef and an enumerated type (an "enum"). A typedef is a mechanism for declaring an alternative name for a type. An enumerated type is an integer type with an associated set of symbolic constants representing the valid values of that type.
Taking the enum first, the full form of an enum declaration consists of the enum keyword, followed by a tag by which that particular enum will be identified, followed by the symbolic enum constants in curly brackets. By default, the enum constants correspond to consecutive integer values, starting at zero. For example:
enum operator { NO_OP, ADDITION
};As you can see, it has some similarities to a struct declaration, and like a struct declaration, variables of that enumerated type can be declared in the same statement:
enum operator { NO_OP, ADDITION
} op1, op2, op3;or they can be declared later, by referencing the enum's tag:
enum operator op4, op5;Also like a struct declaration, the tag can be omitted, in which case the enumerated type cannot be referenced elsewhere in the source code (but any declared variables of that type are still fine):
enum { NO_OP, ADDITION
} op1, op2, op3;Now we get to the typedef. As I already wrote, a typedef is a means to declare an alternative name for a type. It works by putting the typedef keyword in front of something that would otherwise be a variable declaration; the symbol that would have been the variable name is then the alternative name for the type. For instance this ...
typedef unsigned long long int ull_t;declares ull_t to be an alternative name for type unsigned long long int. The two type names can thereafter be used interchangeably (within the scope of the typedef declaration).
In your case, you have
typedef enum
{ NO_OP, ADDITION,
} operator_t;which declares operator_t as an alias for the tagless enumerated type given. Declaring a typedef in this way makes the enum usable elsewhere, via the typedef name, even though the enum is tagless. This is a fairly common mechanism for declaring a shorthand name for an enumerated type, and an analogous technique is common for structs, too.
Bonus (optional): What type of variable is the operator_t?
As I explained, the operator_t is not a variable, it is a type. In particular, it is an enumerated type, and the symbols NO_OP and ADDITION represent values of that type.
Typedefs for enums, structs and unions are a complete waste. They hide important information for the questionable benefit of saving a few characters to type.
Don't use them in new code.
Technically, a typedef introduce an alias, i.e. a new name for something that already exists. This means, typedefs are not new types. The type system will treat them just like the aliased type.
The downvoters may please educate themselves by, for example, reading the wonderful Peter van der Linden book Expert C Programming where the case against typedefs for enum/struct/union is made.
5typedef and enum are two different concepts. You can rewrite the code like this:
enum operator
{ NO_OP, ADDITION
};
typedef enum operator operator_t;The first statement declares an enumeration called operator, with two values. The second statement declares that the enumeration operator is now also to be known as the type operator_t.
The syntax does allow to combine these two statements into one statement:
typedef enum operator { NO_OP, ADDITION, } operator_t;And finally to omit a name for the enumeration, as there is a datatype for it anyway:
typedef enum { NO_OP, ADDITION, } operator_t; Wikipedia has a good discussion of what a typedef is
typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to form complex types from more-basic machine types1 and assign simpler names to such combinations. They are most often used when a standard definition or declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another.See this page for a detailed discussion of Typedef in Wikipedia
Enumerated Types allow us to create our own symbolic names for a list of related ideas.
Given the example you gave I'm guessing you can use enum to select which arithmetic operation to use for a particular set of variables.
The following example code should give you a good idea on what enum is useful for.
enum ARITHMETIC_OPERATION {ADD, SUBTRACT, MULTIPLY};
int do_arithmetic_operation(int a, int b, enum ARITHMETIC_OPERATION operation){ if(operation == ADD) return a+b; if(operation == SUBTRACT) return a-b; if(operation == MULTIPLY) return a*b;
}If you didn't have enum, you would do something like this instead:
#define ADD 0
#define SUBTRACT 1
#define MULTIPLY 2
int do_artithmetic_operation(int a, int b, int operation);This alternative is less readable, because operation is not really an integer but a symbolic type that represents an arithmetic operation that is either ADD, MULTIPLY, or SUBTRACT.
The following links provide good discussions and sample code that uses Enum.
4