自定义类型:结构体,枚举,联合体
结构体的声明
假如要定义一个结构体A
有两种:
1.struct A { 2.struct {
char c; char c;
...(标量、数组、指针、其他结构体等) ...(标量、数组、指针、其他结构体等)
}(它的变量列表) ; }(它的变量列表) ;
第2种定义虽然写起来更方便,但当添加结构体变量的时候就只可以用一次了。
注意:结构体定义并不是定义一个变量,而是定义了一种数据类型,这种类型是自定义的,它可以和语言本身所自有的简单数据类型一样使用(如 int )。
结构体本身并不会被作为数据而开辟内存,真正作为数据而在内存中存储的是这种结构体所定义的变量。
对结构体的访问和赋值通常采用 “.”操作符,即结构体变量名 .成员变量名 如访问A 中的a 就是 x.a
也可以是“->”符,即x->a
结构体内存对齐
之所以内存对齐 原因有二
1.硬件要求;不是所有的硬件平台都能访问任意地址上的任意数据;只能在某些地址处取特定类型的数据。
2.数据结构应该尽可能地在自然边界上对齐,增加cpu的执行效率
至于怎么对齐,直接上例子:
对齐数:该变量所占大小与编译器默认的一个值的较小值。
结构体最大对齐数:结构体中所有变量的对齐数的最大值。(ps:有没有注意到它是不可能超过编译器默认的对齐数~)
对齐规则:1..每个成员变量相对第一个成员变量地址偏移量大小要为此时对齐数的整数倍。2.整个结构体的大小为其最大对齐数的整数倍。3.如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,整个结构体大小要是所有对齐数中的最大对齐数的整数倍
位段:
位段声明和结构体类似,只是
1.位段的成员必须是int\ unsigned int或signed int
2.位段的成员名后面有一个冒号和数字。
位段内存分配:
1. 位段的成员可以是 int 、unsigned int、 signed int 或者是 char (属于整形家族)类型
2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的
3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段
例子:
位段虽然更好节省空间,但有几个跨平台问题:
1. int位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写 成27,在16位机器会出问题。)
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含多个个位段,一个位段成员比较大,无法容纳于当前 剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
枚举和联合体:
枚举:一一列举出来可能的取值。
优点:1. 增加代码的可读性和可维护性
2. 很#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试;
5. 使用方便,一次可以定义多个常量
定义:
(ps: 不再是分号 ,改为了逗号)
{ }中的内容是枚举类型的可能取值,也叫枚常量 。这些可能取值都是有值的,默认从0 开始,一次递增1,当然在定义的时候也可以赋初值。
注意问题:
联合体(共用体):定义的变量包含一系列成员,这些成员公用一块空间。
其定义与用法和结构体极为类似。
特点:联合体的成员共用一块内存的,一个联合体变量的大小,至少是最大成员的大小。当最大成员大小不是最大对齐数的整数倍时,就要使其对齐到最大对齐数的整数倍。
对联合体的典型的应用就是用来判定计算机的存储方式。
#include <cstdio>
int checkSystem()
{
union check
{
int i;
char ch;
}c;
c.i=1;
return (c.ch==1);
}
int main()
{
checkSystem()==1 ? printf("小端!") : printf("大端!");
return 0;
}
如果是大端,此时ch就会输出最高的一个字节也就是:0。
上一篇: 如何解决jQuery和其他库的冲突问题
下一篇: js实现单元格拖拽效果