C++入坑系列(四)复合类型之结构体、共用体和枚举类型

前言

无论在C语言还是C++中,均包含结构体、共用体和枚举类型。由于这三种复合数据类型的概念和使用方法比较简单,所以本文仅对其一些需要注意的内容进行总结。如有疏漏或不足之处,还望各位读者能够不吝指正。

结构体

简介

前面我们学习过的数组,其作用是保存多个相同数据类型的数据。但是在实际应用中,我们往往会遇到更加复杂的情况。比如:我们的学生管理系统,我们不仅需要保存学生的姓名,而且还需要保存学生的班级、学号、年龄等一些列信息,再加上这些信息不能够使用相同的数据类型进行存储,所以便不能使用数组去保存每个学生的详细信息了。
此时,便可以使用结构体数据类型,保存由不同数据类型组成的数据集合了。
简而言之,结构体就是一种可以保存不同数据类型的数据结构。

创建结构体的方法

结构体以struct关键字作为数据类型的标志。在实际使用中,我们可以使用下述三种方法,创建结构体数据类型:
1、常规方式1

struct testStruct
{
	string name;//学生的姓名
	unsigned int core;//学生的分数
	string address;	//学生的地址
};//声明一个结构体数据类型
testStruct structStu1;//C++中创建一个结构体structStu1
//struct testStruct structStu1;//C语言中创建一个结构体structStu1

2、常规方式2

struct testStruct
{
	string name;//学生的姓名
	unsigned int core;//学生的分数
	string address;	//学生的地址
}structStu1,structStu2;//声明一个结构体数据类型,并创建两个结构体structStu1和structStu2

3、利用typedef的方式

typedef struct
{
	string name;//学生的姓名
	unsigned int core;//学生的分数
	string address;	//学生的地址
}testStruct;//声明一个结构体数据类型
testStruct structStu1,structStu2;//创建两个结构体structStu1和structStu2

结构体中的位字段

在嵌入式等底层编程中,往往会遇到结构体的位字段概念,即可以指定结构体成员所占的位数
尤其是涉及到寄存器封装的部分。由于寄存器往往由许多Bit位组成,而每个Bit位所占的位数可能并不相同,所以此时使用结构体的位字段,便可以实现寄存器的内存空间分配。我们以TI的DSP28335芯片的一个寄存器为例进行说明:
在这里插入图片描述

结构体使用技巧

在使用结构体时,如果注意成员变量的位置,那么可以在一定程度上提高程序的执行效率并且节省内存空间。
由于结构体中可以存储不同数据类型的成员,所以在开辟内存空间时,并不是按照固定的大小进行分配的。再加上CPU一般以4个字节作为最优的数据处理大小,所以注意不同数据类型的成员数据的位置,可以对结构体进行优化。
比如:

//声明一个学生的结构体
struct student1
{
	char sex;//学生的性别
	char test;//用于测试的一个字符
	int age;//学生的年龄
};
struct student2
{
	char sex;//学生的性别
	int age;//学生的年龄
	char test;//用于测试的一个字符
};
int main()
{
	student1 stu1 = 
	{
	'M','F',18
	};//定义并初始化一个结构体变量stu1
	cout << "stu1结构体占用的内存大小为:" << sizeof(stu1) << endl;
	student2 stu2 = 
	{
	'M',18,'F'
	};//定义并初始化一个结构体变量stu2
	cout << "stu2结构体占用的内存大小为:" << sizeof(stu2) << endl;
	return 0;
}

输出结果如下:
在这里插入图片描述
为什么相同成员的结构体,所占的内存空间大小却不同呢?
因为在student1结构体中,两个char数据类型是相邻的,由于char数据类型的大小为一个字节,所以4个字节可以保存两个char数据类型的变量,再加上int数据类型的大小为4个字节,所以stu1结构体变量所占的内存空间便是8个字节
但是在student2结构体中,两个char数据类型之间插入了一个int数据类型,第一个char数据类型占据了4个字节中的一个字节,剩下的3个字节无法存储int类型的变量,所以还需要在第二个4字节的空间中保存int数据,而第二个char数据类型还需要再开辟一个4字节大小的空间进行保存,所以最终占用的内存空间大小便是12个字节

共用体

简介

共用体和结构体的作用类似,不同之处在于:
结构体中可以同时存储结构体成员数据,但是共用体只能同时存储一个共用体结构体成员。

共用体的内存分配

通俗的来说,就是在创建结构体变量时,编译器会为结构体中所有的成员开辟内存空间。而在创建共用体变量时,编译器仅会开辟一个内存空间,该内存空间的大小与共用体成员中所占空间最大的成员数据相等。
从内存大小来说,结构体的大小是所有成员数据的大小之和,而共用体的大小是其占用内存最大的成员数据的大小。并且,结构体中的成员数据位于不同的内存地址处,而共用体中的成员数据全部位于同一个地址处。测例如下:

#include <iostream>
#include <cstring>
typedef struct
{
    char name[10];
    double core;
    char address[20];
}stuStruct;
typedef union
{
      char name[10];
      double core;
      char address[20];
}stuUnion;
int main()
 {
     using namespace std;
     stuStruct student1 =
     {"Issac",89.0,"ChengDu"};//初始化结构体
     cout << "结构体占用的内存大小为:" << sizeof(student1) << endl;
     cout << "结构体student1.name的地址:" << &student1.name << endl;
     cout << "结构体student1.core的地址:" << &student1.core << endl;
     cout << "结构体student1.address的地址:" << &student1.address << endl;
     stuUnion student2;
     student2.core = 90.5;
     cout << "共用体占用的内存大小为:" << sizeof(student2) << endl;
     cout << "共用体student2.core的地址:" << &student2.core << endl;
     strcpy(student2.name,"Issac");
     cout << "共用体student2.name的地址:" << &student2.name << endl;
     return 0;
 }

输出结果如下:
在这里插入图片描述

共用体与结构体的结合

在嵌入式开发中,经常需要对寄存器的某个位进行操作,但是也可以对整个寄存器的整体进行操作,完成整个寄存器的赋值操作。此时,便可以使用共用体和结构体,共同完成上述功能。如下所示:
在这里插入图片描述
在实际使用中,我们可以按照下面的说明进行使用:

union GPACTRL_REG GpaCtrlRegs;//创建一个共用体变量
 GpaCtrlRegs.all = 0xFF;//将这个寄存器的所有位设置为1
  GpaCtrlRegs.bit.test = 1;//将该寄存器的test位设置为1

枚举类型

简介

枚举类型的作用与利用define宏定义或者const关键字类似,均是创建常量的一种方式。在创建枚举类型时,使用enum作为该类型的标志。
枚举类型一般用于只能在某个数值范围内进行选择的场合下,比如:每周的七天,每年的12个月等。

创建枚举类型

此处,我们创建一个枚举数据类型,用来表示每周的星期几:

enum week
{
	Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday	
};//默认情况下,枚举类型的数据成员从0开始,比如上面的Monday就等于0,Tuesday等于1
enum week
{
	Monday = 1,Tuesday,Wednesday = 3,Thursday,Friday,Saturday,Sunday	
};//我们也可以人为指定枚举成员的数值,如上所示

为枚举类型分配内存空间

枚举类型的内存分配方法与共用体的方法相似,也仅仅会为整个枚举类型分配一个元素的内存空间的大小,比如:

typedef enum
{
	one = 1,two,three,four
}NUM_ENUM;//声明一个枚举类型
int main()
{
	NUM_ENUM num;//定义一个枚举类型变量
	cout << "枚举数据类型的大小为" << sizeof(num) << endl;//输出的结果为4
	return 0;
}

注意事项

在使用枚举类型时,需要额外注意以下限制:
1、枚举成员的值必须是整型,且同一个枚举变量中,不能有相同的枚举成员!!!比如:

enum testEnum
{
	one = 1,two = 2.0
};//错误,枚举类型只能是整型数据
enum testEnum
{
	one = 1,two = 2,one = 3
};//错误。同一个枚举类型中,不能出现相同的枚举成员

2、访问枚举成员时,必须访问枚举类型中存在的枚举成员,不能访问不存在的成员。
3、虽然枚举成员可以被认为是相应的整型数据,但是不能直接将一个整型数据赋值给一个枚举变量,但是可以利用强制类型转换实现,比如:

enum testEnum
{
	one = 1,two = 2
};
testEnum test1;
test1 = 1;//错误,及时枚举成员中的one实际上就是1
test1 = (testEnum)(1);//正确

总结

上述三种复合数据类型,在实际的工程开发中,也是会经常出现的。虽然概念上不难理解。但是在实际使用时,还是需要注意各个数据类型的注意事项。尤其是在使用共用体时,需要注意其内存分配原则。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值