自定义类型—结构体,位段,联合

来源:互联网 发布:java nanotime 编辑:程序博客网 时间:2024/05/16 23:37

结构体

结构的声明:必须列出它包含的所有元素(包括类型和名字)
例:

struct SIMLIE{//SIMPLE为这个结构的名字或者标签int a;int b;int c;};

我们可以看到这个结构没有定义变量,在后续的程序中如果想要定义结构的变量,我们可以直接使用这个结构的名字来直接定义结构变量

struct SIMPLE simple;

其实啊,在C语言总还有一种定义结构体类型的方法,那就是用typedef
例:

typedef struct {int a;int b;int c;}Simple;

此时这个和结构标签的效果几乎相同!!但是此时的Simple为一个结构体类型的名字,而之后的声明可以像下面的样子

Simple x;Simple *z;

结构体成员的访问
首先结构体成员的访问是通过(.)操作符来访问的,.操作符的左边为结构变量的名字,右边为要访问成员的名字
其实我们还可以用间接访问的方式来访问结构体的的成员,用结构体的指针来访问,我们可以定义一个结构体指针就可以来访问他的结构体成员了!!!
举个栗子

Simple *s;s->a;

注意箭头的左部必须是一个指针!!!

结构体的自引用
结构体的自引用正不正确取决于这个结构体的大小可不可以被确定!!!

结构体的不完整声明
有时候一些结构体之间会存在一些互相引用的关系也就是说一个结构体包含了另一个结构体的一个或多个成员。和自引用一样至少有一个结构必须在另一个结构内部用指针的方式存在!!那么那个结构体应该首先定义呢!!这个时候我们的不完整声明就登登登登闪亮登场了!!

我们可以先对其中的一个结构体进行一个不完整的声明,它声明了一个作为结构标签的标识符,然后我们就可以吧这个标签用在不需要知道这个结构长度的声明中。举个栗子:

struct B;struct A{struct B *p;};struct B{struct A *p;};

此时我们的结构体A和B就都被声明了!!

结构体中还存在一个很重要!!肥肠肥肠重要的问题!!
那就是内存对齐问题
首先我们要明白为什么会有内存对齐问题
大部分的参考资料都是如是说的:

1、平台原因(移植原因):
不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

2、性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。
原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问。

内存对齐的四个规则
1.第一个成员在与结构体变量偏移量为0的地址处。
2.其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
//对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
linux中的默认值为4
3.结构体总大小为最大对齐数(每个成员变量除了第一个成员都有一个对齐数)的整数倍。
4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

位段

位段是一个和结构体肥肠相像的结构来我们举个栗子

struct CHAR{unsigned ch:7;unsigned font:6;unsigned size:8;};

就多了一个:而已但是位段的声明不可以随意声明。首先,位段成员必须是int,unsigned int,signed int类型,冒号后边是该位段占用的位的数目!!所以注重可移植性的程序还是避免使用位段!!

联合体

联合体最重要的一点是联合提体的所有成员共用同一段内存,即这个联合体所有的成员的地址都是相同的。举个栗子

union {int a;float b;char c[4];}x={5};

此时x={5};这条语句就是对联合体的初始化但是对联合体的初始化仅仅必须是联合第一个成员的类型,并且它必须位于一对花括号里,此条语句就等于把x.a初始为5

联合体的占用内存空间大小取决于它的最长的成员的大小

结尾贴一个自己写的详细讲解结构体对齐问题的一个博客各位大佬们要是没事可以看看!!
http://blog.csdn.net/qq_36767247/article/details/78767504