电子文档交易市场
安卓APP | ios版本
电子文档交易市场
安卓APP | ios版本
换一换
首页 金锄头文库 > 资源分类 > DOC文档下载
分享到微信 分享到微博 分享到QQ空间

枚举大小sizeof中枚举的大小详解

  • 资源ID:21420945       资源大小:41.32KB        全文页数:5页
  • 资源格式: DOC        下载积分:10金贝
快捷下载 游客一键下载
账号登录下载
微信登录下载
三方登录下载: 微信开放平台登录   支付宝登录   QQ登录  
二维码
微信扫一扫登录
下载资源需要10金贝
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
如填写123,账号就是123,密码也是123。
支付方式: 支付宝    微信支付   
验证码:   换一换

 
账号:
密码:
验证码:   换一换
  忘记密码?
    
1、金锄头文库是“C2C”交易模式,即卖家上传的文档直接由买家下载,本站只是中间服务平台,本站所有文档下载所得的收益全部归上传人(卖家)所有,作为网络服务商,若您的权利被侵害请及时联系右侧客服;
2、如你看到网页展示的文档有jinchutou.com水印,是因预览和防盗链等技术需要对部份页面进行转换压缩成图而已,我们并不对上传的文档进行任何编辑或修改,文档下载后都不会有jinchutou.com水印标识,下载后原文更清晰;
3、所有的PPT和DOC文档都被视为“模板”,允许上传人保留章节、目录结构的情况下删减部份的内容;下载前须认真查看,确认无误后再购买;
4、文档大部份都是可以预览的,金锄头文库作为内容存储提供商,无法对各卖家所售文档的真实性、完整性、准确性以及专业性等问题提供审核和保证,请慎重购买;
5、文档的总页数、文档格式和文档大小以系统显示为准(内容中显示的页数不一定正确),网站客服只以系统显示的页数、文件格式、文档大小作为仲裁依据;
6、如果您还有什么不清楚的或需要我们协助,可以点击右侧栏的客服。
下载须知 | 常见问题汇总

枚举大小sizeof中枚举的大小详解

至从 C 语言开始 enum 类型就被作为用户自定义分类有限集合常量的方法被引入到了语言当中,而且一度成为 C+中定义编译期常量的唯一方法(后来在类中引入了静态整型常量) 。根据上面对 enum 类型的描述,有以下几个问题:1.到底 enum 所定义出来的类型是一个什么样的类型呢?2.作为一个用户自定义的类型其所占用的内存空间是多少呢?3.使用 enum 类型是否真的能够起到有限集合常量的边界约束呢?4.大家可能都知道 enum 类型和 int 类型具有隐示(自动)转换的规则,那么是否真的在任何地方都可以使用 enum 类型的变量来代替 int 类型的变量呢?1. 到底 enum 所定义出来的类型是一个什么样的类型呢?在 C+中大家都知道仅仅有两种大的类型分类:POD 类型(注(1 ) )和类类型。enum 所定义的类型其实属于 POD 类型,也就是说它会参与到 POD 类型的隐示转换规则当中去,所以才会出现 enum 类型与 int 类型之间的隐示转换现象。那么也就是说 enum 所定义的类型不具备名字空间限定能力(因为不属于类类型) ,其所定义的常量子具备和 enum 类型所在名字空间相同的可见性,由于自身没有名字限定能力,所以会出现名字冲突现象。如:struct CETypeenum EType1 e1, e2 ;enum EType2 e1, e2 ;上面的例子会出现 e1、e2 名字冲突编译时错误,原因就在于枚举子(e1 、e2)是 CEType名字空间中的名字,同样在引用该 CEType 中的枚举子时必须采用 CEType:e1这样的方式进行,而不是 CEType:EType1:e1来进行引用。注(1)POD 类型:你可以将 POD 类型看作是一种来自外太空的用绿色保护层包装的数据类型,POD 意为“Plain Old Data”(译者:如果一定要译成中文,那就叫“彻头彻尾的老数据 ”怎么样!)这就是 POD 类型的含义。其确切定义相当粗糙(参见 C+ ISO 标准) ,其基本意思是 POD 类型包含与 C 兼容的原始数据。例如,结构和整型是 POD 类型,但带有构造函数或虚拟函数的类则不是。 POD 类型没有虚拟函数,基类,用户定义的构造函数,拷贝构造,赋值操作符或析构函数。为了将 POD 类型概念化,你可以通过拷贝其比特来拷贝它们。此外, POD 类型可以是非初始化的。2. 作为一个用户自定义的类型其所占用的内存空间是多少呢?该问题就是 sizeof( EType1 )等于多少的问题,是不是每一个用户自定义的枚举类型都具有相同的尺寸呢?在大多数的32位编译器下(如: VC+、gcc 等)一个枚举类型的尺寸其实就是一个 sizeof( int )的大小,难道枚举类型的尺寸真的就应该是 int 类型的尺寸吗?其实不是这样的,在 C+标准文档(ISO14882)中并没有这样来定义, 标准中是这样说明的:“枚举类型的尺寸是以能够容纳最大枚举子的值的整数的尺寸” ,同时标准中也说名了:“枚举类型中的枚举子的值必须要能够用一个 int 类型表述” , 也就是说,枚举类型的尺寸不能够超过 int 类型的尺寸,但是是不是必须和 int 类型具有相同的尺寸呢?上面的标准已经说得很清楚了,只要能够容纳最大的枚举子的值的整数就可以了,那么就是说可以是 char、short 和 int。例如:enum EType1 e1 = CHAR_MAX ;enum EType2 e2 = SHRT_MAX ;enum EType3 e3 = INT_MAX ;上面的三个枚举类型分别可以用 char、short 、int 的内存空间进行表示,也就是:sizeof( EType1 ) = sizeof( char );sizeof( EType2 ) = sizeof( short );sizeof( EType3 ) = sizeof( int );那为什么在32位的编译器下都会将上面三个枚举类型的尺寸编译成 int 类型的尺寸呢?主要是从32位数据内存对其方面的要求进行考虑的,在某些计算机硬件环境下具有对齐的强制性要求(如:sun SPARC) ,有些则是因为采用一个完整的32位字长 CPU 处理效率非常高的原因(如: IA32) 。所以不可以简单的假设枚举类型的尺寸就是 int 类型的尺寸,说不定会遇到一个编译器为了节约内存而采用上面的处理策略。3. 使用 enum 类型是否真的能够起到有限集合常量的边界约束呢?首先看一下下面这个例子:enum EType e1 = 0, e2 ;void func1( EType e )if ( e = e1 )/ do something/ do something because e != e1 must e = e2void func2( EType e )if ( e = e1 )/ do somethingelse if ( e = e2 )/ do somethingfunc1( static_cast( 2 ) );func2( static_cast( -1 ) );上面的代码应该很清楚的说明了这样一种异常的情况了,在使用一个操出范围的整型值调用func1函数时会导致函数采取不该采取的行为,而第二个函数可能会好一些他仅仅是忽略了超出范围的值。这就说明枚举所定义的类型并不是一个真正强类型的有限常量集合,这样一种条件下和将上述的两个函数参数声明成为整数类型没有任何差异。所以以后要注意标准定义中枚举类型的陷阱。(其实只有类类型才是真正的强类型)4. 是否真的在任何地方都可以使用 enum 类型的变量来代替 int 类型的变量呢?通过上面的讨论,其实枚举类型的变量和整型变量具有了太多的一致性和可互换性,那么是不是在每一个可以使用 int 类型的地方都可以很好的用枚举类型来替代呢?其实也不是这样的,毕竟枚举类型是一个在编译时可区分的类型,同时第2点的分析枚举类型不一定和 int 类型具有相同的尺寸,这两个差异就决定了在某些场合是不可以使用枚举类型来代替 int 类型的。如:第一种情况:enum EType e1 = 0, e2, e3 ;EType val;std:cin >> val;第二种情况:enum EType e1 = 0, e2, e3 ;EType val;std:scanf( "%d", &val );上面的两种情况看是基本上属于同一种类型的问题,其实不然。第一种情况会导致编译时错误,会因为 std:cin 没有定义对应的枚举类型的重载>>运算符而出错,这就说明枚举类型是一种独立和鉴别的类型;而第二种情况不会有任何编译时问题,但是可能会导致 scanf 函数栈被破坏而使得程序运行非法,为什么会这样呢?上面已经分析过了枚举类型变量的尺寸不一定和 int 类型相同,这样一来我们采用%d 就是说将枚举类型变量 val 当作4字节的 int 变量来看待并进行参数压栈,而在某些编译器下 sizeof( val )等于1 字节,这样 scanf 函数就会将 val 变量地址中的后续的三字节地址也压入栈中,并对其进行赋值,也许 val 变量后续的三个字节的地址没有特殊含义可以被改写(比如是字节对齐的空地址空间) ,可能会认为他不会出现错误,其实不然,在 scanf 函数调用结束后会进行栈清理,这样一来会导致 scanf 函数清理了过多的地址空间,从而破坏了外围函数的栈指针的指向,从而必然会导致程序运行时错误。由上面的说明枚举类型有那么多的缺点,那我们怎样才能够有一个类型安全的枚举类型呢?实际上,在最新的 C+0x 标准草案中有关于枚举作用域问题的提案,但最终的解决方案会是怎样的就无法未卜先知了,毕竟对于象 C+ 这样使用广泛的语言来说,任何特性的增删和修改都必须十分小心谨慎。当然,我们可以使用一些迂回的方法来解决这个问题(C+ 总是能给我们很多惊喜和意外) 。例如,我们可以把枚举值放在一个结构里,并使用运算符重载来逼近枚举的特性:struct FileAccess enum _Enum Read = 0x1,Write = 0x2;_Enum _value; / 枚举值FileAccess(int value = 0) : _value(_Enum)value) FileAccess& operator=(int value) this->_value = (_Enum)value;return *this;operator int() const return this->_value;我们现在可以按照希望的方式使用这个枚举类型:FileAccess access = FileAccess:Read;并且,因为我们提供了到 int 类型的转换运算符,因此在需要 int 的地方都可以使用它,例如 switch 语句:switch (access) case FileAccess:Read:break;case FileAccess:Write:break;当然我们不愿意每次都手工编写这样的结构。通过使用宏,我们可以很容易做到这一点:#define DECLARE_ENUM(E) struct E public: E(int value = 0) : _value(_Enum)value) E& operator=(int value) this->_value = (_Enum)value; return *this; operator int() const return this->_value; enum _Enum #define END_ENUM() ; private: _Enum _value; ;我们现在可以按如下的方式定义前面的枚举,并且不比直接写 enum 复杂多少。DECLARE_ENUM(FileAccess)Read = 0x1,Write = 0x2,END_ENUM()DECLARE_ENUM(FileShare)Read = 0x1,Write = 0x2,END_ENUM()

注意事项

本文(枚举大小sizeof中枚举的大小详解)为本站会员(宝路)主动上传,金锄头文库仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即阅读金锄头文库的“版权提示”【网址:https://www.jinchutou.com/h-59.html】,按提示上传提交保证函及证明材料,经审查核实后我们立即给予删除!

温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




关于金锄头网 - 版权申诉 - 免责声明 - 诚邀英才 - 联系我们
手机版 | 川公网安备 51140202000112号 | 经营许可证(蜀ICP备13022795号)
©2008-2016 by Sichuan Goldhoe Inc. All Rights Reserved.