1. A brief example of the use of enum
When writing programs, we often need to associate a set of optional alternative attributes for an object. For example, students' grades are A, B, C, D, etc., and weather is sunny, cloudy, rainy, etc.
More commonly, there may be three states when opening a file: input, output and append. Typically, 3 constants are defined accordingly, namely:
const int input = 1;
const int output = 2;
const int append = 3;
Then, call the following function:
bool open_file(string file_name, int open_mode);
for example,
open_file("Phenix_and_the_Crane", append);
This approach is relatively simple, but it has many disadvantages. The main point is that it cannot limit the value range of the second parameter passed to the open_file function. As long as the value of type int is passed, it is legal. (Of course, the response in this case is to judge the value of the second parameter within the open_file function, and it will only be processed within the ranges of 1, 2, and 3.)
Using enumerations can alleviate this embarrassment to a certain extent (Note 1). It not only implements functions similar to the previous definition of three constants, but also combines these three values into a unique group. For example:
enum open_modes {input = 1, output, append};
The above defines open_modes as the enumeration type enumeration type. Each named enum is a unique type and is a type indicator type specifier. For example, we can rewrite an open_file function:
bool open_file(string file_name, open_modes om);
In the open_modes enumeration, input, output, and append are called enumerator enumerators, which define the value range of objects defined by open_modes. At this time, calling the open_file function is exactly the same as the previous method:
open_file("Phenix_and_the_Crane", append);
However, if the second parameter passed to open_file is not the value of the open_modes enumeration type (Note 1), the compiler will recognize the error; even if the value of the parameter is equivalent to one of the input, output, and append, an error will still occur! For example:
open_file("Phenix_and_the_Crane", 1);
2. Definition of enumeration
An enum is a type that can save a set of values portrayed by the user. For definitions, enumerations are used much like an integer type.
The definition of an enum has the following form, namely, starting with the keyword enum, followed by an optional enumeration name, which is a list of enumerators separated by a comma by braces {}:
enum [enumeration name] {enumerator1[=value1], enumerator2[=value2], ...};
3. Types and values of enumerators
The type of the enumerator is the enumeration where it is located. For example, in the open_modes enumeration mentioned above, the types of the enumerator such as input, output and append are all open_modes. This approach is actually to give users and compilers some tips on the proposed use of this variable.
By default, the first enumerator is assigned a value of 0, and the next enumerator value is the value of the previous enumerator +1, for example:
enum weather {sunny, cloudy, rainy, windy};
in
sunny == 0,
cloudy == 1,
rainy == 2,
windy == 3;
The above is the default. Sometimes we want to explicitly specify the value of an enumerator, so what happens? have a look:
enum some_fruit {apple = 3, orange, banana = 4, bear};
OK, apple == 3, banana == 4; So what about orange and bear? Remember to say before, by default, "The next enumerator value is the value of the previous enumerator +1". Since these two enumerations do not have explicit assignments, they will follow the default rules, so orange == 4, bear == 5.
It can also be seen from this example that the value of the enumerator in the same enum does not need to be unique. What's the use of this? Here is a simple example:
enum some_big_cities {
Guangzhou = 4,
Shenzhen = 4,
Hongkong = 4,
Shanghai = 2,
Beijing = 3,
Chongqi = 3
};
The above simply classifies the five cities according to the region by region.
4. Definition, initialization and assignment of enumeration variables
Since each enum is a type, variables can naturally be declared by this type, for example, some_big_cities defined earlier:
some_big_cities where_I_am;
It should be noted that it is not initialized when declaring where_I_am. If the value of where_I_am is printed at this time:
enum some_big_cities {
Guangzhou = 4,
Shenzhen = 4,
Hongkong = 4,
Shanghai = 2,
Beijing = 3,
Chongqi = 5};
int main(void)
{
some_big_cities wh;
cout<<"the value is: "<<wh<<endl;
return 0;
}
The output will be the value is: 1. However, if wh is declared as a global variable, another case:
enum some_big_cities {Guangzhou = 1 Shenzhen = 1, Hongkong = 1,
Shanghai = 2, Beijing = 3, Chongqi = 5};
some_big_cities wh;
int main(void)
{
cout<<"the value is: "<<wh<<endl;
return 0;
}
The output will be the value is: 0;
The above results are obtained in Visual C++ 2005 Express. I don’t know how the other compilers are, and I don’t know why I get such results. Let's find information later.
When defining an enumeration variable, you can initialize it, for example:
some_big_cities wh = Guangzhou;
Note that only one of the enumeration subs can be taken to the right of the equal sign; especially, taking Guangzhou as an example, although Guangzhou==4, the following initialization is an error:
some_big_cities wh = 4;
Visual C++ 2005 compiler tips:
error C2440: 'initializing' : cannot convert from 'int' to 'some_big_cities'
It can be seen that an integer cannot be assigned directly to an enumeration variable, because enumeration and integer are of different types unless explicitly converted. Let’s talk about the relationship between enumeration and integers later.
In addition to initialization, enumeration variables also have assignment operations:
some_big_cities wh;
wh = Guangzhou;
wh = Shanghai;
or
some_big_cities wh1 = Guangzhou;
some_big_cities wh2 = Shanghai;
wh2 = wh1;
5. Enumeration value range
If the values of all enumerations in an enumeration are not negative, the range of representation of the enumeration is [0:2^k-1], where 2^k is the smallest power of 2 that can make all enumerations lie within this range; if there is a negative enumeration value, the range of value of the enumeration is [-2^k, 2^k-1]. For example:
enum e1 {dark, light}; //Scope 0:1
enum e3 {min = -10, max = 1000}; //Range-1024:1023
6. The relationship between enumeration and integer
Integer values can only be explicitly converted to an enum value, but if the result of the conversion is outside the enum value range, the result is undefined.
enum e1 {dark = 1, light = 10};
e1 VAR1 = e1(50); //No definition
e1 VAR2 = e1(3); //Compiled by
This also explains why implicit conversion from integer to enum is not allowed, because most integer values do not have corresponding representations in specific enums.
As for examples where enumerations can be used as specific integer numbers, you can understand them from open_modes.
7. Custom operators
Enumeration is a user-defined type, so the user can define its own operations for it, such as ++ or <<, etc. However, before definition, enumerations like integers can not be used by default, for example:
enum SomeCities
{
zhanjiang,
Maoming,
Yangjiang,
Jiangmen,
Zhongshan
};
SomeCities oneCity;
for (oneCity = zhanjiang; oneCity != Zhongshan; ++oneCity)
{
cout<<oneCity<<endl;
}
The above ++OneCity is not defined, and the following error is obtained under Visual C++ 6 compilation:
error C2675: unary '++' : 'enum main::SomeCities' does not define this operator or a conversion to a type acceptable to the predefined operator
8、Sizeof
An enum type sizeof is a sizeof of an integer that can accommodate its range, and it will not be greater than sizeof(int), unless the value of an enumerator cannot be represented by int or unsigned int.
In 32-bit machines, sizeof(int) is generally equal to 4. All the enums mentioned earlier, for example,
enum SomeCities
{
zhanjiang,
Maoming,
Yangjiang,
Jiangmen,
Zhongshan
};
Calculate its sizeof, which may be 1 or 4. In my Intel E2160 dual-core, 32-bit machine, I get 4.
-----------------------------------------------------------------------------------
[Note 1, Begin]
Since it is possible to obtain the value of the corresponding enum type by explicitly converting integer numbers, it is still too difficult to declare an enum to limit the range of parameters passed to the function.
Here is an example:
enum SomeCities
{
zhanjiang=1, //1
Maoming, //2
Yangjiang, //3
Jiangmen, //4
Zhongshan = 1000 //1000
};
void printEnum(SomeCities sc)
{
cout<<sc<<endl;
}
int main(void)
{
SomeCities oneCity = SomeCities(50); //Explanation of 50 is used to assign a value to oneCity
printEnum(oneCity); //Get 50 output under VC++ 6 compiler
return 0;
}
The above example shows that although there is no enum value assigned to 50 in the definition of SomeCities, since 50 is within the value range of the enum, a defined enum value is obtained by explicitly declaring, which is successfully passed to the printEnum function.