enum,struct,union类型使用和长度
VC,C++ Builder和lcc三个编译器 间枚举类型enum长度的情况.
各种C编译器默认的字节对齐数不一致,要写通用的代码,经常就是使用
#pragma pack(1) ...
#pragma pack()
来使编译器以单字节对齐.
今天在bcb5中调用vc6的dll时出现错误,但在VC中调用dll却很正常,说明很有可能是编译器之间的差异造成.仔细debug后发现bcb和vc的枚举类型长度不一样,即便使用了#pragma pack(1)编译开关. 如以下程序: /*---------------------*/ #pragma pack(1) typedef enum { ENUMITEM1=0, ENUMITEM2, ENUMITEM3 } ENUM; #pragma pack() ENUM mENUM; sizeof(mENUM); /*---------------------*/
在VC6和LCC3.3中为四字节,而在BCB中即为1字节.再试以下程序
/*---------------------*/
#pragma pack(4)
typedef enum {
ENUMITEM1=,
ENUMITEM2,
ENUMITEM3
} ENUM;
#pragma pack()
ENUM mENUM;
sizeof(mENUM);
/*---------------------*/
在VC和LCC中依然是4字节,而在BCB中也还是1字节,由于手上暂时没有GCC,所以不能看GCC的情况.
以上说明枚举类型作为C的标准变量类型,其长度是不受编译开关影响的,就如char类型无论如何pack,依然是单字节.
但是,并非所有的编译器都遵循C标准,或许是VC不标准,或许是BCB不标准.
所以建议以后用到的变量尽量使用char或int来替代enum,以免带来不必要的麻烦.
#include <stdio.h>
int main()
{
enum Color
{
GREEN = ,
RED,
BLUE,
GREEN_RED = ,
GREEN_BLUE,
}c;
printf("%d,%d,%d,",GREEN,RED,BLUE);
printf("%d,%d\n",GREEN_RED,GREEN_BLUE);
printf("%d\n",sizeof(c));
;
}
看到这里,是不是一开始想用c.GREEN,c.RED,c.BLUE...来表示枚举变量里面的成员?然后这样子表示,编译器是会报错的。为什么不能像结构体那样表示呢?因为结构体里面的成员是变量,而枚举里面的成员是常量啊!(这是我个人的理解)
枚举变量究竟是多大呢?答案是4,为啥呢?因为,枚举变量的取值为花括号内的任意一个值(有且只能有其中一个值),而这个值是int型的,在X86系统中,int型的数据占内存4个字节。所以sizeof(c) = ,也就是枚举变量的值为4。
一般编译器都有选项的 BCB: * -b Make enums integer-sized (-b- makes them short as possible) GCC: -fshort-enums Use the narrowest integer type possible for enumeration types VC Same as int
枚举默认是用int类型来存储的,32位系统下占4个字节。可以存储的最大值是0xffffff。 你可以改变枚举的大小例如enum TypeChar : unsigned char{} 这样可以节省空间, 在嵌入式编程中较为常见。嵌入式编程中,甚至有用位来存储的。
枚举并不放在类的对象里,类A里面没有任何东西,与class A {};相同大小。不包含任何东西的类的大小就是1。cout << sizeof(A) << endl;输出的是1
关于C++和C的区别:
1.区别最大的是struct,C++中的struct几乎和class一样了,可以有成员函数,而C中的struct只能包含成员变量。 enum,union没区别。2.C++要考虑字节对齐。
struct的定义:
struct 结构标签
{
类型1 标识符1;
类型2 标识符2;
类型3 标识符3;
类型4 标识符4;
类型5 标识符5;
};
、建议将struct的声明和变量的定义分开写,
、struct内可以放任何类型的变量声明。
struct的内存对齐:
对齐原则:
、数据成员对齐规则。每个数据成员存储的起始位置要从该成员大小的整数倍开始。
、数据成员包含结构体:结构体成员要从其内部最大元素大小的整数倍地址开始存储。
、结构体的总大小:是其内部最大基本成员的整数倍,不足的要补齐。
这个似乎不太重要,没有太大的关系。也就是某些面试或考试题中的难为人的地方了。
union的定义:
union 联合标签
{
类型1 标识符1;
类型2 标识符2;
类型3 标识符3;
类型4 标识符4;
类型5 标识符5;
};
联合体与结构体的区别:
、结构体中,每个变量依次存储。
、联合体中,每个变量都是从偏移地址零开始存储,每次只有一个成员存储于该地址。
enum的定义:
, large =,humungous};
、枚举通过简单的操作将一串名字和一串整型值相联系起来。
、缺省情况下,枚举从零开始,如果对列表中的某一个标识符赋值,下一个标识符值比前面一个的值大1.
、#define 定义的值在编译时候消失,但是枚举定义的,则在调试的过程任然是可见的,可以在代码调试中使用它们。
其实 enum可以相对应define来使用。
举个例子:
union a
{
int b;
char c;
};
a abc;
abc.b=;
abc.c=;
//或者也可以直接在定义时定义变量
union a
{
int b;
char c;
}abc;
abc.b=;
abc.c=;
或者:
typedef union
{
int b;
char c;
}a;
a abc;
abc.b=;
abc.c=;
仔细的看看,很重要,老是用的不对,自己给自己找麻烦的。
/////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////
struct的最终大小考虑是最大的那个类型的倍数和每个都要对齐;
enum的大小考虑是最大的那个
enum是枚举,就是某个变量的值是能够列举的,比如,星期的话就每周1到7,月的话就1到12、而struct的话是对于某个变量是有很多数据类型构成一个总体的,比如学生这个变量,他需要学号,姓名,年龄,性别等等,这个时候就需要定义结构体了。而uninon的话呢,其中定义的变量都只占一同块内存。。。
对于结构体:考虑要对齐和占用最大空间的元素所占空间的倍数
对于联合体:考虑是里面所有类型数据占用空间的倍数同时还要比最大的那个还要大的最小数,就是联合体占用的空间,注意数组类型的处理!!!
typedef enum
{
ANUnknown = ,
ANShapeFile = ,
ANSDEDatabase = ,
ANFileDatabase = ,
ANRasterFile =
}ANDataType;
======================================================
struct AAA
{
double d;
char ss;
char s;
};
, 则整个为 * = , 因为 ,剩余一个不足8 按 8字节计算。比如:
struct AAA
{
double d;
char s1;
char s2;
char s3;
char s4;
char s5;
char s6;
char s7;
char s8;
char s9;
};
按结构体中的变量的长度叠加,则大小为 +(+++++++)+ = , < < , 则结构体的大小为
比如,
struct AAA
{
double d;
char s1;
int i;
};
按结构体中的变量的长度叠加,则大小为 ++ = , < < , 则结构体的大小为
======================================================
union AAA
{
double d;
int i;
};
联合,则以定义中最大的数据类型的长度为准,此联合的 size 为
备注: union 与 struct 的大小与其内部定义的函数无关!!!
typedef struct与struct的区别
. 基本解释
typedef为C语言的关键字,作用是为一种数据类型定义一个新名字。这里的数据类型包括内部数据类型(int,char等)和自定义的数据类型(struct等)。
在编程中使用typedef目的一般有两个,一个是给变量一个易记且意义明确的新名字,另一个是简化一些比较复杂的类型声明。
至于typedef有什么微妙之处,请你接着看下面对几个问题的具体阐述。
. typedef & 结构的问题
当用下面的代码定义一个结构时,编译器报了一个错误,为什么呢?莫非C语言不允许在结构中包含指向它自己的指针吗?请你先猜想一下,然后看下文说明:
typedef struct tagNode
{
char *pItem;
pNode pNext;
} *pNode;
答案与分析:
、typedef的最简单使用
typedef long byte_4;
给已知数据类型long起个新名字,叫byte_4。
、 typedef与结构结合使用
typedef struct tagMyStruct
{
int iNum;
long lLength;
} MyStruct;
这语句实际上完成两个操作:
) 定义一个新的结构类型
struct tagMyStruct
{
int iNum;
long lLength;
};
分析:tagMyStruct称为“tag”,即“标签”,实际上是一个临时名字,struct 关键字和tagMyStruct一起,构成了这个结构类型,不论是否有typedef,这个结构都存在。
我们可以用struct tagMyStruct varName来定义变量,但要注意,使用tagMyStruct varName来定义变量是不对的,因为struct 和tagMyStruct合在一起才能表示一个结构类型。
) typedef为这个新的结构起了一个名字,叫MyStruct。
typedef struct tagMyStruct MyStruct;
因此,MyStruct实际上相当于struct tagMyStruct,我们可以使用MyStruct varName来定义变量。
答案与分析
C语言当然允许在结构中包含指向它自己的指针,我们可以在建立链表等数据结构的实现上看到无数这样的例子,上述代码的根本问题在于typedef的应用。
根据我们上面的阐述可以知道:新结构建立的过程中遇到了pNext域的声明,类型是pNode,要知道pNode表示的是类型的新名字,那么在类型本身还没有建立完成的时候,这个类型的新名字也还不存在,也就是说这个时候编译器根本不认识pNode。
解决这个问题的方法有多种:
)、
typedef struct tagNode
{
char *pItem;
struct tagNode *pNext;
} *pNode;
)、
typedef struct tagNode *pNode;
struct tagNode
{
char *pItem;
pNode pNext;
};
注意:在这个例子中,你用typedef给一个还未完全声明的类型起新名字。C语言编译器支持这种做法。
)、规范做法:
struct tagNode
{
char *pItem;
struct tagNode *pNext;
};
typedef struct tagNode *pNode;
enum,struct,union类型使用和长度的更多相关文章
- 关于C与C++的struct,union,enum用法差异
对着代码说话: #include <stdio.h> #include <stdlib.h> struct test { int abc; }; enum _enum {A,B ...
- C/C++中struct/union/class内存对齐
struct/union/class内存对齐原则有四个: 1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储 ...
- C++11的enum class & enum struct和enum
C++11的enum class & enum struct和enum C++标准文档--n2347(学习笔记) 链接:http://www.open-std.org/jtc1/sc22/wg ...
- [转]C++11的enum class & enum struct和enum
1. 旧版enum存在的问题 问题 描述 1 向整形的隐式转换(Implicit conversion to an integer) 2 无法指定底层所使用的数据类型(Inability to spe ...
- 【转】C++11的enum class & enum struct和enum
转自:https://blog.csdn.net/sanoseiichirou/article/details/50180533 C++标准文档——n2347(学习笔记) 链接:http://www. ...
- C语言中Union类型的使用方法
转自:http://blog.csdn.net/feimor/article/details/6858103 使用C语言时,常常使用struct,对于union类型却几乎没有用过,只知道它是联合类型, ...
- c# (ENUM)枚举组合类型的谷歌序列化Protobuf
c# (ENUM)枚举组合类型的谷歌序列化Protobuf,必须在序列化/反序列化时加上下面: RuntimeTypeModel.Default[typeof(Alarm)].EnumPassthru ...
- MySql获取表的字段名称、字段注解、字段类型、字段长度
SELECT COLUMN_NAME as '列名',COLUMN_COMMENT,DATA_TYPE as '字段类型' ,COLUMN_TYPE as '长度加类型' FROM informat ...
- 关于mysql varchar 类型的最大长度限制
Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. This ...
随机推荐
- 【BZOJ 3504】[Cqoi2014]危桥
Description Alice和Bob居住在一个由N座岛屿组成的国家,岛屿被编号为0到N-1.某些岛屿之间有桥相连,桥上的道路是双 向的,但一次只能供一人通行.其中一些桥由于年久失修成为危桥,最多 ...
- 面试问到的Spring
一.介绍Spring 1.主要使用了基本的javabean代替的Ejb Ejb:服务端的组件模型,设计目标应用部署分布在应用程序,把已经做好的编好的程序,打包放在服务 端执行,凭借java跨平台的优 ...
- 移动端material风格日期时间选择器
原文 好多时候在移动端需要一个的日期选择器,由于在应用上有可能应用各种框架库(Vue.js, React.js, zepto.js等):所以说一个无依赖的,这样易于上层进行封装.直接开门见山,先来张动 ...
- 【BZOJ】【1013】【JSOI2008】球形空间产生器sphere
高斯消元 高斯消元模板题 /************************************************************** Problem: 1013 User: Tun ...
- NYOJ-469 擅长排列的小明 II AC 分类: NYOJ 2014-01-02 22:19 159人阅读 评论(0) 收藏
最初的第一印象是和组合数一个性质的题目.所以用了回溯法,结果,你懂的... #include<stdio.h> #include<math.h> void dfs(int n, ...
- GameMap其他初始化
//其他初始化 init_prop();//初始化道具 init_ornamemtal();//初始化装饰物 init_monster_type_info();//初始化怪物基本信息 这个比较重要在加 ...
- 关闭VS时, 每次都 会弹出 保存以下各项的更改吗?
如果是添加项目, 或修改了解决方案的配置, 会弹出这个是正常的. 如果在没有修改的情况下还这样就是有问题的. 原因: 在Vs中安装了PowerDesigner插件, 并在VS中点了该插件的东西 ...
- [设计模式] 19 观察者模式 Observer Pattern
在GOF的<设计模式:可复用面向对象软件的基础>一书中对观察者模式是这样说的:定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新.当一个 ...
- sp_MSforeachtable使用方法 查看库中所有表的空间大小
sp_MSforeachtable使用方法 1)说明系统存储过程sp_MSforeachtable和sp_MSforeachdb,是微软提供的两个不公开的存储过程,从ms sql 6.5开始.存放在S ...
- UNDERSTANDING CALLBACK FUNCTIONS IN JAVASCRIPT
转自: http://recurial.com/programming/understanding-callback-functions-in-javascript/ Callback functio ...