现在的位置: 首页 > 综合 > 正文

C++的enum类型分析

2013年02月09日 ⁄ 综合 ⁄ 共 3814字 ⁄ 字号 评论关闭

enum在实际中应用比较少,容易被忽略。其实enum 和 struct、class一样,都是用户自定义类型。既然是自定义类型,就可以有他的数据成员,还有成员函数!

For example:
    enum e{a=1 , b=2 , c=4};
那么:
    001: enum e e1;        //enum e不是对象,它是类型,e1才是类型enum的对象!
    002: e e1;                //e是类型enum e的简写
    003: e1 = 1;              //错误!int不能赋值给一个用户自定义类型
    004: e1 = e();            //默认构造函数
    005: e1 = e(1)           //从int构造enum e类型对象的构造函数
    006:e1 = a;              //默认调用“拷贝构造函数”

enum的“取值范围”和“内存分配”

如何确定一个enum的取值范围?
For example:
            enum e1{ a=2, b=4 };

首先找到其绝对值的最大值,但为了容易理解,先不谈负数,也就是先找到其最大值,这里的最大值是4。
4 用二进制表示就是 100,也就是需要3bits才能最小的容纳下4这个值,而3bits所能表示的范围是 0-7,于是e1的取值范围为[0,7]。

现在来看看负数,
            enum e2{ a=-2, b=4 };
其中绝对值最大的是4,需要3bits才能容纳下,但因为可以取负值(而最大元素b=4不是负值),也就是说需要增加一个符号位,那么就需要4bits。
4bits的取值范围是 1000 - 0111(二进制表示),也就是 -8 到 7(十进制表示)。
enum e3{ a=-4, b=2 } 就只需要3bits,取值范围是[-4,3]。

简单的说就是找到最少的能容纳下所有的元素的位数

因为C++标准规定超出枚举类型表示范围的赋值结果是undefined的,也就是说 e2 x = (e2)6 是肯定正确的,而 e2 y = (e2)8 行为是未定义的。

enum的内存分配,如 e2 需要3bits,那么C++规定e2的尺寸只要容得下3bits就行,到底是取1个byte,还是4个byte,还是...,那由编译器自己决定。但是,C++标准在这里有个限制:1<= sizeof(enmu)<=sizeof(int)。

 

 

以上内容参考自Bjarne Stroustrup的 The C++ Programming Languane .

原文如下:

4.8 Enumerations [dcl.enum]
    An enumeration is a type that can hold a set of values specified by the user. Once defined, an enumeration is used very much like an integer type.Named integer constants can be defined as members of an enumeration. For example,
    enum { A S M , A U T O , B R E A K };

    defines three integer constants, called enumerators, and assigns values to them. By default, enumerator values are assigned increasing from 0 , so A S M ==0 , A U T O ==1 , and B R E A K ==2 . An enumeration can be named. For example:
    enum keyword {A S M ,A U T O ,B R E A K };
Each enumeration is a distinct type. The type of an enumerator is its enumeration. For example,
    A U T O is of type keyword .
Declaring a variable k e y w o r d instead of plain i n t can give both the user and the compiler a hint as to the intended use. For example:
void   f(keyword   key )
{
    switch (key) {
        c a s e A S M :
                    / / do something
                b r e a k ;
        c a s e B R E A K :
                    / / do something
                break ;
        }
}
A compiler can issue a warning because only two out of three k e y w o r d values are handled.An enumerator can be initialized by a constantexpression(§C.5) of integral type (§4.1.1). The range of an enumeration holds all the enumeration’s enumerator values rounded up to the nearest larger binary power minus 1 . The range goes down to 0 if the smallest enumerator is nonnegative and to the nearest lesser negative binary power if the smallest enumerator is negative. This defines the smallest bitfield capable of holding the enumerator values. For example:
    enum e1 { dark , light }; // range 0:1
    enum e2 { a = 3 , b = 9 }; // range 0:15
    enum e3 {min = 10 ,m a x = 1000000}; // range 1048576:1048575
A value of integral type may be explicitly converted to an enumeration type. The result of such a conversion is undefined unless the value is within the range of the enumeration. For example:
    enum flag { x =1 , y =2 , z =4 , e =8 }; // range 0:15
            flag f1 = 5 ; // type error: 5 is not of type flag
            flag f2 = flag (5 ); // ok: flag(5) is of type flag and within the range of flag
            flag f3 = flag (z |e ); // ok: flag(12) is of type flag and within the range of flag
            flag  f4 = flag (99); // undefined: 99 is not within the range of flag
The last assignment shows why there is no implicit conversion from an integer to an enumeration; most integer values do not have a representation in a particular enumeration. The notion of a range of values for an enumeration differs from the enumeration notion in the
Pascal family of languages. However, bitmanipulation examples that require values outside the set of enumerators to be welldefined
have a long history in C and C++.

    The sizeof an enumeration is the s i z e o f some integral type that can hold its range and not larger than sizeof (i n t ), unless an enumerator cannot be represented as an i n t or as an u n s i g n e d i n t . Forexample, sizeof (e 1 ) could be 1 or maybe 4 but not 8 on a machine where s i z e o f (i n t )==4 .By default, enumerations are converted to integers for arithmetic operations (§6.2). An enumeration
is a userdefined type, so users can define their own operations, such as ++ and << for an enumeration(§11.2.3).

 

 

抱歉!评论已关闭.