C++结构体、联合体、枚举体及其内存
结构体:是一种特殊形态的类
结构体与类的区别:结构体与类具有不同的默认访问控制属性:
在类中,对于未指定访问控制属性的成员,其访问控制属性为私有类型;在结构体中,对于未指定任何访问控制属性的成员,其访问控制属性为公有型。
关键字:struct
定义:
Struct 结构体名称
{
公有成员;
Protected:
保护型成员
Private:
私有成员
};
什么时候用结构体而不用类:
1:主要用来保存数据,而没有什么操作的类型
2:人们习惯将结构体的数据成员设置为公有,因此这时用结构体比较方便
如果:
1:一个结构体的全部数据成员都是公共成员;
2:没有用户定义的构造函数;
3:没有基类和虚函数;
那么这个结构体可以通过下列方式初始化:
类型名 变量名 = { 成员数据1初值, 成员数据2初值, …… };
例如:
struct student
{
char name[20];//姓名
int num;//学号
int age;//年龄
float score;//分数
};
student wh={"wh",1529401160,20,98.0};
其中student为结构体的类型名;wh为结构体变量名
结构体的内存大小:
以字节最大的单位 为地址对齐标准,如 结构体中 最大为 double,8个字节,那么 比它小的单位就要凑齐 8的整数倍字节大小。
例如:
struct test1
{
char w;
int s;
double q;
}m;
char 1字节,int 4字节, double 8字节,所以以8字节对齐,总字节大小为8的倍数
8+4+1=13,而8字节对齐后,为16。
再例如:
struct test2
{
char w[5];
int s[2];
double q;
}n;
w[5]:5字节,s[2]:8字节,q:8字节
5+8+8=21,对齐8字节后为24
struct test3
{
double r;
char k[9];
}s;
s 的大小为24
typedef union {
Short i;
int k[5];
char c;
} Mat;
Typedef struct {
int i;
Mat j;
double k;
}Like;
则语句 printf("%d",sizeof(Like)+sizeof(Mat));的执行结果是:52
联合体
联合体的全部数据成员共享一组内存单元,任何两个成员不会同时有效
关键字:union
定义:
union 联合体名称
{
公有成员;
Protected:
保护型成员
Private:
私有成员
};
定义变量方法:在定义union联合体名称之后如:
union mark
{
char grade;
bool pass;
int percent;
}wh;
或者先定义联合体类型,再定义变量:
union mark
{
char grade;
bool pass;
int percent;
};
mark wh;
初始化方法:wh.grade=’A’;或wh.pass=Ture;或者wh.percent=90;
存储方式:共享一组内存单元,每一项元素起始地址都一样,都跟联合体 union 的地址偏移量为0
例如:union mark
{
char grade;
bool pass;
int percent;
};
存储方式:
mark | grade | pass | percent |
---|---|---|---|
* | * | * | * |
* | * | ||
* | * | ||
* | * |
存储空间:4字节
联合体的内存计算:此结构的容量要容纳最大的一个元素,而且要字节对齐其他元素的大小
例如:
union U
{
char s[9]; //9个字节
int n; //4个字节
double d; //8个字节
};
union U中最大的是 9 个字节的 s[9],但 9 不能被 4 和 8 同时整除,而16可以,且16比9大。
所以 联合体所占空间 为16 个字节
union C{
int i;
char x[2];
}a;
int main(void)
{
a.x[0] = 10;
a.x[1] = 1;
printf("%d\n",a.i);
return 0;
}
由于 PC 机位小端序,因此 低字节放低地址,同时a是全局变量存储在静态存储区,默认初始为0,对 x[2]赋值后,union C的地址空间的值为:
高地址0000 0000|0000 0000|0000 0001| 0000 1010 低地址(4个字节的存储空间)
所以输出 1×2的八次方+1×2的三次方+1×2 = 266;
如是在函数体内定义变量则其内存的值是不确定的需要先将其清0
union u{
int i;
char x[2];
};
int main(void)
{
union u a;
memset(&a,0,sizeof(a)); //这步很关键,否则 union 的起始内存地址不会全是0,而是不确定会造成无法预测 union u a 中 元素的值
a.x[0] = 10;
a.x[1] = 1;
printf("%d\n",a.i);
return 0;
}
枚举体
定义方法:
enum class 枚举类型名: 底层类型 {枚举值列表};
enum class Typename1 {General, Light, Medium, Heavy};
(不定义底层类型默认int,里面的值分别对应0,1,2,3)
enum class Typename2: char{General, Light, Medium, Heavy};
enum class Typename3 {General=4, Pistol, MachineGun, Cannon};(里面的值分别对应4,5,6,7)
特点:
强作用域,其作用域限制在枚举类中
转换限制,枚举类对象不可以与整型隐式地互相转换
可以指定底层类型
详解见:https://www.runoob.com/w3cnote/cpp-enum-intro.html
参考文章:https://blog.csdn.net/Jaihk662/article/details/79706768
https://blog.csdn.net/u014453898/article/details/53705448