结构体(struct)是C语言重应用比较多的一种数据结构,它可以有效的各种数据(包括各种不同类型的数据)整合
在一个数据体中,可以更好的实现程序的结构化,更方便的管理数据及其对数据的操作。
在嵌入式系统开发中,一方面由于系统资源的严重不足,另一方面各种变量相互通信,相互作用,正确合理使用结构体不仅可以为系统节约一部分宝贵的资源,而且还可以简化程序的设计,使软件设计的鲁棒性和可维护性都大大增强。
以下程序都在Windows 2000+Visual C++ 6.0上调试通过。
首先考察结构体的大小(size):
struct a
{
unsigned char code;
unsigned int student;
};
如果按照各个数据的各自的大小进行累加,结构体a的size应该是:sizeof(char)+sizeof(int)=5;
而实际上,以上程序的运行结果为:the size of struct a is 8。
为什么会出现这样的情况?
这是因为在32位的操作系统上,操作系统组织数据是以32位(4个字节)作为一个标准,因此各种变量的size都
一般都是4的倍数。而且结构体数据都是按照定义时所使用的顺序存放的,因此尽管code变量只会占有一个字节,但是code+student=5>4,因此第一个4位字节存放code,第二个4位字节用于存放student,这样实际上就浪
费了3个字节。
有了上面的例子,后面的例子也就不难理解了:
struct b
{
unsigned char code;
unsigned char result;
unsigned int student;
};
结构体b的size仍然是8,code+result共2个字节,实际上占据了4个字节的容量,这样就浪费了2个字节。
以下结构体的浪费更为明显:
struct c
{
unsigned char code;
unsigned int student;
unsigned char result;
};
结构体c的size是12,这是因为sizeof(code)<4,但是sizeof(code+student)在4与8之间,因此实际上code占
据了4个字节,student占据了4个字节,同样的道理result也将占据4个字节,sizeof(c)=12,这样就总共浪
费了6个字节的容量。
因此,对于潜入式系统和电子系统的设计来说,由于系统资源的不足,这方面的情况更需要格外的考虑,在
设计上更改以下数据定义的顺序,有可能使得这样的情况得到缓解。例如,结构体b和结构体c所定义的数据
实际上是相同的,因为定义的顺序不同,结构体b所浪费的字节数远远小于结构体c所浪费的字节数。
比特域是一种由结构体扩展而来的数据结构组织形式,也称为位域,占位符等。类似下面的定义:
struct card{
unsigned int pips:4;//占据4个位的长度
unsigned int suit:2;
unsigned char kq:2;
...}
跟在变量声明后面的非负正常数是该数据所占据的比特宽度,比特宽度最多是机器字的长度,对于PC机和
Windows操作系统而言,这个值是32。一个32位的int型数据可以存放的数据范围是极大的,在我们的程序中
往往并不需要这样大的表示范围,因此,使用比特域把数据压缩到一定的表示范围内,可以有效的节省程序
所需要的内存量,这在系统内存容量极为有限的嵌入式系统开发中是很重要的!
在上面的结构中,card变量拥有一个4比特的域pips来存贮0--15的非负整数,一个2比特的域suit来存贮
0--3以及一个2比特的域kq。
实际上,上面定义中的int和char在很多情况下也是可以省略掉的,这样在比特域中所定义的数据结构实际上
就与这些基本类型是无关的,只是表示一定区域的一些有符号整形数或者无符号整形数。因此,在声明变量
的时候unsigned或者signed是必须注明的,因为编译器需要确切的知道所定义的变量的精确取值范围。
但是,应该注意的是:不同的编译器对于比特域如何分配是有不同定义的,而且使用比特域组织的程序往往
可移植性不好,因此,除非是确实需要节省内存,否则比特域(包括联合)最好不要使用。