结构体struct和联合体union以及enum枚举体5的区别
2013-07-02 19:32 youxin 阅读(1048) 评论(0) 编辑 收藏 举报
下面来自wikipedia:
In computer science, a union is a value that may have any of several representations or formats; or it is a data structure that consists of a variable which may hold such a value. Some programming languages support special data types, called union types, to describe such values and variables. In other words, a union type definition will specify which of a number of permitted primitive types may be stored in its instances, e.g., "float or long integer". Contrast with arecord (or structure), which could be defined to contain a float and an integer; in a union, there is only one value at any given time.
A union can be pictured as a chunk of memory that is used to store variables of different data types. Once a new value is assigned to a field, the existing data is overwritten with the new data. The memory area storing the value has no intrinsic type (other than just bytes or words of memory), but the value can be treated as one of several abstract data types, having the type of the value that was last written to the memory area.
In type theory, a union has a sum type.
Depending on the language and type, a union value may be used in some operations, such as assignment and comparison for equality, without knowing its specific type. Other operations may require that knowledge, either by some external information, or by the use of a tagged union.
http://en.wikipedia.org/wiki/Union_type
Difference between Union and Structure
A union is a class all of whose data members are mapped to the same address within its object. The size of an object of a union is, therefore, the size of its largest data member.
In a structure, all of its data members are stored in contiguous memory locations. The size of an object of a struct is, therefore, the size of the sum of all its data members.
This gain in space efficiency, while valuable in certain circumstances, comes at a great cost of safety: the program logic must ensure that it only reads the field most recently written along all possible execution paths. The exception is when unions are used for type conversion: in this case, a certain field is written and the subsequently read field is deliberately different.
An example illustrating this point is:
+-----+-----+ struct { int a; float b } gives | a | b | +-----+-----+ ^ ^ | | memory location: 150 154 | ˇ +-----+ union { int a; float b } gives | a | | b | +-----+
Structures are used where an "object" is composed of other objects, like a point object consisting of two integers, those being the x and y coordinates:
typedef struct { int x; // x and y are separate int y; } tPoint;
Unions are typically used in situation where an object can be one of many things but only one at a time, such as a type-less storage system:
typedef enum { STR, INT } tType; typedef struct { tType typ; // typ is separate. union { int ival; // ival and sval occupy same memory. char *sval; } } tVal;
更多参考:http://www.chinaunix.net/old_jh/23/179471.html
1.由于结构体每个成员都有自己的存储空间,所有所有成员可以同时存储,而共用体的所有成员都共享一个存储空间,同一时间只能存储一个成员。
2.结构体变量可以在定义时初始化,而共用体变量不能在定义时初始化。
如下面的程序是非法的:
union Person{ int age; double salary; }u={1,5,5};
3.结构体变量中的成员可以同时存储,可以通过指针或变量单独引用每个成员;而共用体同一时间只能存储一个成员,可以通过指针或变量单独引用所存储的成员,并且所引用的是最后一次存入成员的值,例如;
union Person{ int age; double salary; }u; int main() { u.age=10; u.salary=1.1; cout<<u.salary<<endl; }
输出:1.1
如果我们输出u.age,会发现是一个很乱的数字。
我们把age和salary都改成int,如下:
union Person{ int age; int salary; }u; int main() { u.age=-32768; u.salary=1; cout<<u.salary<<endl; cout<<u.age<<endl; }
输出:都输出1,。证明了age和salary共享内存。
Ansi c 允许2个同类型的共有体变量之间赋值,和结构体类似。
共用体变量的应用
他可以增加程序的灵活性,对同一段内存空间的值在不同情况在不同情况下做不同的用途。至少有2方面的用途。
1.应用在数据处理中
如在一个学校的人员管理中,对教师应登记其“单位”,对学生应登记其“班级”,他们都在同一栏中。
struct { long num; char name[20]; char sex; char job; union { int className;//班级 char group[20];//单位名 }category; }person[10]; int main() { cin>>person[0].job; if(person[0].job=='s')//s代表Student cin>>person[0].category.className; else if(person[0].job=='t')//t代表teacher cin>>person[0].category.group; //cout if(person[0].job=='s') cout<<person[0].category.className<<endl; else if(person[0].job=='t') cout<<person[0].category.group<<endl; }
2.发现数据的底层存储形式。
利用共用体的特点区分整形变量的高字节和低字节。
union change { char c[2]; short int i; }un; int main() { un.i=1; printf("%d ",un.c[0]); printf("%d ",un.c[1]); }
输出:1,0。
结构体最常用的就是大小端的判断:
bool isSmall() { union{ char c; int x; }un; un.x=1; if(un.c==1) cout<<"小端"<<endl; else cout<<"大端"<<endl; return un.c==1; }
小端:低位低地址,高位高地址。
大端:低位高地址,高位低地址。
Intel cpu 都是小端存储。
enum 所谓枚举类型,是指这种类型的变量的值只能是所指定的若干名字之一。例如一个枚举类型和枚举变量可以定义成:
enum colorName{ red,yellow,blue,white,black}; (C++struct可以省略struct,而enum不能省略,即不能这么定义变量:
colorName c1,而必须是:
enum colorName c1,c2;
变量c1是colorName类型,其值只能是red,yellow,blue,white,black 五者之一。
赋值如:
c1=red;或c1=white。
而下面的语句不合法
c1=green;
需要说明的几点:
1.enum是关键字,标识枚举类型,定义枚举必须用enum开头。
2.定义enum时,花括号中的一些名字(red,yellow等)都是程序设计者自己指定的,命名规则和标识符相同。这些名字没有固定含义,只是一个符号。程序设计者为了可读性才使用这些名字。这些名字不是变量,不能改变其值,例如:
下面的不对: red=3,scanf("%d",red);
3.它的值是一些整数,从花括号中的第一个名字开始,各名字分别代表0,1,2,3,4。这是系统自动赋予的。如:
printf("%d",red) 输出的值为0.
但是定义枚举时不能写成:
enum ColorName {0,1,2,3,4};
必须用符号red,yellow或其他标志符,这些符号称为枚举常量或枚举元素。
4.可以在定义类型时对枚举常量初始化。
enum ColorName{red=3,yellow,blue,white=8,black};
这是red值为3,yellow为4,blue为5,white为8.black为9.
5.枚举常量可以进行比较:
if(c1==red) printf("red");
if(c1>red)
if(c1<white).
他们是按照所代表的整数进行比较的。
6.一个枚举变量的值只能是几个枚举 常量之一。可以将一个枚举变量赋给另一个枚举变量。但不能讲一个整数赋值给他。
c1=black;正确
c1=5;//错误
7.枚举常量不是字符串,不是用下面的方法输出字符串red:
printf("%s",red);
可以先检查color的值,如果是red,就输出字符串red。
enum string { x1=5, x2, x3, x4, }; enum string x=x3;
此时,枚举变量x3实际上是7。
常用枚举
enum Weekday {sunday,monday,tuesday,wednesday,thursday,friday,saturday};
遍历枚举:
好多资料都是这样说的;
enum ColorName{ red,yellow,blue,white,black}; int main() { enum ColorName c1; for(c1=red;c1<black;c1=c1+1) { switch(c1) { case red: cout<<"red"; break; } } }
我编译错误:
rror C2440: “=”: 无法从“int”转换为“ColorName。
为什么?因为c1+1变成了1,(枚举和整形数据相运算)是整形,而整形不能赋值给枚举类型。