1.6 结构体、公用体、枚举
1.6.1 结构体、共用体、枚举的概念
1.?结构体的声明方法
结构体的声明方法如下所示:
struct 结构名{
数据类型 成员名;
数据类型 成员名;
...
};
成员表由若干成员组成,每个成员都是该结构的一个组成部分,对每个成员也必须做类型声明。例1.11说明了结构体的使用方法。
【例1.11】 结构体使用范例。
#include<iostream>
#include<string.h>
using namespace
std;
struct student{ // 声明一个结构体类型student
int num;
char name[20];
int age;
}; // 最后有一个分号
int main(){
struct student stu1; // 定义一个student类型的变量stu1
student stu2; // 定义时也可以不用struct
stu1.num=1; //
单独对st1的num元素赋值
char temp[20]="Xiao ming";
strncpy(stu1.name,temp,strlen(temp));
stu1.age=10;
cout<<stu1.num<<"
"<<stu1.name<<" "<<stu1.age<<endl;
student *stu3=&stu1; // stu3是结构体的指针,指向stu1
(*stu3).num=2; // stu1的num值被修改成了2;
cout<<stu1.num<<"
"<<stu1.name<<" "<<stu1.age<<endl;
return 0;
}
程序的执行结果是:
1 Xiao ming 10
2 Xiao ming 10
例1.11中声明了一个结构体类型student,定义了两个student类型的变量stu1和stu2,分别用了两种定义方法,分别是前面有struct关键字和没有struct关键字。这两种定义方法都是可以的,显然没struct关键字的使用更为方便。
引用结构体变量中成员的一般方式为:
结构体变量名.成员名
例1.11中,stu1.num表示结构体变量stu1中的成员数量的值。
指针也可以应用于结构体,例1.11中stu3就是一个结构体变量,指向stu1。
2.?共用体
共用体,用关键字union来定义,它是一种特殊的类。在一个共用体里可以定义多种不同的数据类型,这些数据共享一段内存,在不同的时间里保存不同的数据类型和长度的变量,以达到节省空间的目的。但同一时间只能储存其中一个成员变量的值。
共用体的声明方式为:
union 共用体类型名{
数据类型 成员名;
数据类型 成员名;
...
}变量名;
可以使用union判断系统是big endian(大端)还是little endian(小端)。
【例1.12】 判断系统是big endian还是little endian。
#include<iostream>
using namespace
std;
union TEST{
short a;
char b[sizeof(short)];
};
int main(){
TEST test;
test.a=0x0102;// 不能引用共用体变量,只能引用共用体变量中的成员。
if(test.b[0]==0x01&&test.b[1]==0x02){
cout<<"big
endian."<<endl;
}
else
if(test.b[0]==0x02&&test.b[1]==0x01){
cout<<"small
endian."<<endl;
}
else{
cout<<"unknown"<<endl;
}
return 0;
}
程序的执行结果是:
small endian.
其中,big endian是指低地址存放最高有效字节,little endian则是低地址存放最低有效字节。如果将0x1234abcd写入0x0000开始的内存中,则结果如表1-2所示。
表1-2 big endian和little endian的内存地址增长方向
地址 big endian little endian
0x0000 0x12 0xcd
0x0001 0x34 0xab
0x0002 0xab 0x34
0x0003 0xcd 0x12
表1-2展示了0x1234abcd分别在big endian的系统和在little endian的系统上的内存地址是怎么样分布的。例如0x0000是1Byte的存储单元,0x12单元一共占了8bit,也就是1byte,即占用了1Byte。
目前,几乎所有网络协议都是采用big endian的方式来传输数据的,当两台采用不同字节序的主机通信时,在发送数据之前都必须经过字节序的转换成为网络字节序(big endian)后再进行传播。
3.?枚举
在实际问题中,有些变量的取值被限定在一个有限的范围内。例如,一个星期只有7天,一年只有12个月,一个班每周有6门课程等。如果把这些量说明为整型,字符型或其他类型显然是不妥当的。为此,C语言提供了一种称为“枚举”的类型,枚举类型在C++中也同样适用。在“枚举”类型的定义中列举出所有可能的取值,用来说明该“枚举”类型的变量取值不能超过定义的范围。应该说明的是,枚举类型是一种基本数据类型,而不是一种构造类型,因为它不能再分解为任何其他基本类型。
枚举的声明方式为:
enum 枚举类型名{枚举常量表列};
如同结构和共用体一样,枚举变量也可用不同的方式说明,即先定义后说明,同时定义说明或直接说明。
设有变量a, b, c是枚举类型weekday,可采用下述任一种方式:
enum weekday{
sun,mou,tue,wed,thu,fri,sat };
enum weekday
a,b,c;
或者为:
enum weekday{
sun,mou,tue,wed,thu,fri,sat }a,b,c;
或者为:
enum {
sun,mou,tue,wed,thu,fri,sat }a,b,c;
枚举值是常量,不是变量。不能在程序中用赋值语句再对它赋值。
例如对枚举weekday的元素再作以下赋值,都是错误的:
sun=5;
mon=2;
sun=mon;
只能把枚举值赋予枚举变量,不能把元素的数值直接赋予枚举变量,如下面的语句是正确的:
a=sum;
b=mon;
而下面的语句则是错误的:
a=0;
b=1;
如一定要把数值赋予枚举变量,则必须用强制类型转换,如:
a=(enum
weekday)2;
其意义是将顺序号为2的枚举元素赋予枚举变量a,相当于:
a=tue;
还应该说明的是枚举元素不是字符常量也不是字符串常量,使用时不要加单、双引号。
【例1.13】 enum使用范例。
#include<iostream>
using namespace
std;
int main(){
enum weather{sunny,cloudy,rainy,windy};
/*其中sunny=0,cloudy=1,rainy=2,windy=3,
默认地,第一个枚举子被赋值为0*/
enum fruits{apple=3,orange,banana=7,bear};
/*也可以显式地赋值,接下来的枚举子取值是前面一个枚举子的取值+1,即orange=4,bear=8*/
cout<<orange<<endl;
enum big_cities{guangzhou=1,shenzhen=3,
eijing=1,shanghai=2};
/*同一枚举中的枚举子的取值不需要是唯一的*/
return 0;
}
程序的执行结果是:
4
例1.13中定义了3个枚举类型:weather、fruits和big_cities,其中weather中的枚举子都被显式地赋值了,fruits中的枚举子只赋值了其中几个,没显式赋值的则是前面一个枚举子的取值+1。同一枚举类型中的枚举子的取值不需要是唯一的,可以相同。