【C】浅谈c语言里面的结构体和位段!!!

来源:互联网 发布:淘宝卷皮 编辑:程序博客网 时间:2024/05/20 21:42

结构体的定义:

首先,在c语言里面的结构体定义所用到的关键字是struct,看下面一段代码:

#define _CRT_SECURE_NO_WARNINGS 1#include <stdio.h>struct A{int i;char j;}q,w;                   //直接在结构体类型后面定义结构体变量struct S{int a;double b;char c;    struct A ss;      //结构体里面包含其他的结构体};int main(){struct S s = {2,3.14,'q',{3,'v'}};       //给结构体变量s初始化struct S *ps = &s;                     //定义结构体指针printf("%lf\n",ps->b);return 0;}

先定义了两个结构体类型,struct A和struct  S,在这两个结构体类型里面又定义构体变量有两种方式,一种是直接在结构体类型之后定义结构体变量名、另外一种是在结构体类型外面定义一个结构体变量,例如:结构体变量s的定义。

结构体的初始化:

结构体初始化和数组的初始化类似,使用一对大括号来进行初始化

struct Stu                //结构体的定义{char name[20];int age;char sex[5];int number[12];};int  main(){struct Stu s = {"zhansan",21,"nan",{2,0,1,5,2,7}};     //结构体初始化return 0;}
给结构体初始化时候就按照结构体的成员进行初始化。

结构体的typedef 

有时候定义一个结构体需要的struct  ****时候会很麻烦,这时就可以用typedef来对这个结构体进行重命名,例如:

typedef struct{int a;char c;}Stu;int main(){Stu s = {1,'c'};return 0;}
这里typedef struct将结构体进行重命名为Stu,以后初始化时候就可以拿Stu直接进行初始化,这样就不用写struct关键字,从而减少代码的书写和减少代码的长度。

结构体在内存里面的存储

先来看一段代码:

struct Stu {char c;int a;};int main(){    printf ("%d\n",sizeof(struct Stu));return 0;}

这段代码的运算结果是8,?????为什么呢??????

解析

在结构体在内存里存储的时候有自己的内存对齐规则,在vs环境里面的默认是8个字节,linux里面是4个字节。

1、结构体的第一个成员始终都在结构体的0偏移位置

2、从第二个成员开始都要对齐到某个对齐书的整数倍(对齐数为结构体成员大小和默认对齐数的较小值)

3、结构体的总大小必须是最大对齐数的整数倍。

上面代码在内存里面是


char c只占一个字节,从1开始到3都不是4(int a)的整数倍,到第4个字节的时候开始存储a,向后占4

个字节到7字节时候存储完成,一共占据了8 个字节大小,刚好8是最大对齐数4的整数倍,所以该结构体的大小是8.

再看一个例子:

struct  A{char b;int d;};struct Stu {char c;int a;char m;struct A s;};int main(){    printf ("%d\n",sizeof(struct Stu));return 0;}
这个代码输出的结果是20.?????为什么?????

原来,在结构体里面包含结构体的时候A的大小是8(char b占据0字节,int b占据4-7字节,共8个字节),再看Stu,char c占据0字节、int a占据4-7字节、char m占据8字节、struct A s占据11-19字节。共20字节。

在结构体里面包含结构体的时候应该按照结构体里面的成员的对齐数进行对齐!!!!!
位段

前面讲了对齐数,但是这一行的存储方式会造成很多内存的浪费,下来我们看看位段

1、位段成员必须声明为int,signed int,unsigned int类型,其次,在成员名的后面是一个冒号的一个整数,这个整数指定改位段所占用的位的数目。

2、位段的成员在内存里面是从左到右还是从右到左 的存储方式是不确定的(根据环境的不同而改变)

3、当指定两个位段时候,第二个位段比较大,无法容纳于第一个剩余的空间时候,第二个位段全部存储于第一个剩余的空间还是将第一个位段剩余的空间占满后剩下的存储到下一个字节,这些都是根据ide环境不同而不同的。

这些是位段的主要特点,这些也说明了位段是一个不跨平台的。

在vs编程环境里面的位段

struct Stu {int a:2;char c:3;signed b:10;};int main(){    printf("%d\n",sizeof(struct Stu));return 0;}
输出的值是12。

对齐原因

平台问题:不是所有的硬件平台都能访问任意地址的数据的,某些硬件平台只能在某些地址处取特定类型数据,否则就会发出硬件异常。

性能原因:数据结构应尽可能的在边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次内存访问,而对齐的内存只需要访问一次。

笔者能力有限,如有大佬找到错误,一定一定要在下面留言来告知我,感激不尽!!!!