Bootstrap

struct 结构体大小 结构体定义 位段(位域)

结构体的定义方式

//使用方式一
struct 结构体名
{
  int a;
  int b;
  char x;
}; //需要分号
struct 结构体名 变量名;
//使用方式二 声明与定义同时进行
struct 结构体名
{
   int a;
   int b;
}变量名;
//使用方式三  直接进行定义
struct 
{
  int a;
  int b;
}stu1;
//使用方法四   使用typedef 重新定义一个数据类型
typedef struct stu
{
  int a;
  int b;
}stu,*pstu; 
其中stu表示的是 struct stu 
    *pstu表示的是 struct stu *
使用方法   stu stu1; 等价于struct stu stu1
          pstu stu1; 等价于struct stu* stu1;

结构体大小的计算

//一、结构体成员的偏移量必须是成员大小的整数倍(0被认为是任何数的整数倍)

//二、结构体大小必须是所有成员大小(数组,结构体除外)的整数倍
//对齐方式浪费空间 但是效率提升 提升计算机对内存的效率
指针的大小就是4字节

struct s2{
char ch1;//1   偏移3个数     1           0        
int i;//  4
char ch2; //1   
};
计算 得到的结构体大小是12 
数据类型的大小  偏移值
1                0
4                1+3
1                8
此时的结构体大小是 1+8等于9 不是最大的数类型的整数倍 因此最终是12
struct s1
{
   char c;//1                1         0
   char c1;//1               1         1
          //                 4         2+2               4+4等于8      
   int a;
};
结构体的大小是84的整数倍
struct s3{
char ch;  //1     1      0
int i;  //8       4      1+3
char str[10];//   10      8   
};
当前的成员的大小是18 不是4的整数倍 因此该结构体的大小是20  当前的数组的大小是12字节
当该数组的大小是12的时候 大小是204的整数倍   大小是20
当该数组的大小是14的时候 大小是22 不是4的整数倍 因此是24   当前的数组大小占用16个字节
struct s4{
		char ch;//1
		int i;  //4  3    //8个字节
        //结构体里面应该是多少字节就是多少字节  不会进行对齐和其他的结构体成员 最开始的是16   现在的是32字节 
        //如果下面的float没有  则是40 个字节		  
        int zz;  //4  
        int cc;  //4
		float f; //4    //20个字节   但是要满足里面的类型的大小的倍数     24 要满足最大是
        
        struct s//一共16个字节    32 
		{     
			char ch1;//1
			int j;//  4   3
            char ch2;
            int i;  
            double x;//
          double c;           
			double d;//8个字节  
        }stem;//如果结构体后面有东西表示的是一个结构体变量
}mm;
上面的是结构体中又嵌套了一个结构体  进行计算
结构体上面的大小是20个字节
嵌套的结构体stem大小是40个字节   
因此总共是60个字节 但是不是最大的数据类型double8的倍数  因此最终大小是64

将上面的结构体进行改变

struct s4{
		char ch;//1
		int i;  //4  3    //8个字节
        //结构体里面应该是多少字节就是多少字节  不会进行对齐和其他的结构体成员 
        int zz;  //4  
        int cc;  //4
		float f; //4    //20个字节   但是要满足里面的类型的大小的倍数     24 要满足最大是
        double x;//              
        struct s//
		{     
			char ch1;//1
			int j;//  4   3
            char ch2;  
        }stem;//如果结构体后面有东西表示的是一个结构体变量
}mm;
除了stem结构体的大小是32
stem的结构体大小是12 
但是stem因为要适应double 8的倍数 因此stem的大小是16 
因此 该结构体大小是16+32  48
当删除上面的double类型的变量的时候
结构体的大小是32
struct s5{
	char ch; // 1
	int i;   //4   3   8
	union{//联合体 算的是里面最大的值   //4
	char ch1;
	int j;
	//double zz;  最大时8
	};
	char x; 1  
};
联合体算的是最大的值所占用的大小  里面最大的是int类型 因此是4个字节
13不是4的倍数 因此是16
因此大小是16个字节
添加上double 以后
为17 因为不是最大类型double的倍数
因此时24
#pragma pack(4)  //指定向4对齐 最大是8
              //如果不定义这个就是24个字节  因为最大的是8 也要是8的倍数
struct s6{
	char ch;  //1   0
	int i ;   //4   1+3  
	float f;  //4   8
	double d; //8   12  向4对齐   所以这个结构体的大小是20
};
最终的结果等于12+8 =20  因为指定向4对齐 因此结构体的大小是20
#pragma pack(10)//如果元素大小没有超过元素最大值  就按照里面最大的 进行对齐
                //成员里面没有超过10   所以按照最大值进行计算
                
/*
1     0
4     1+3
4     4+4
8     12         
*/
struct s7{
char ch;//1
int i;//  4  3   8
float f; //4    12
double d;  //8    20      24 变成d的倍数  
};
因为里面没有超过10的,因此按照里面的最大类型的字节数
最终计算得到的是20 不是8的倍数  因此要变成24

结构体间的赋值

相同类型的结构体之间可以直接进行赋值

struct stu
{
  int a;
  int b;
  char c[20];
};

int main()
{
  struct stu xiaoming ={111,22,"xiaoming"};
  struct stu lisi;
  //两者属于相同的结构体类型,可以直接进行赋值
  lisi=xiaoming;
  //执行printf lisi的输出的结果就是xiaoming上面的赋值的结果
}

结构体数组

定义方法

struct stu
{
  int a;
  int b;
  char c[20];
};

struct stu edu[3];//定义了一个struct stu类型的结构体数组edu
/* 该数组有三个元素edu[0] edu[1] edu[2] */

/*结构体数组元素的使用*/
结构体数组名[下标].成员
edu[0].a=11;

结构体指针

/*  结构体在使用的时候,需要进行开辟内存空间 */
struct stu *zhangsan=NULL;
/*  结构体进行开辟内存空间后才能进行赋值 */
zhangsan = (struct stu*)malloc(sizeof(struct stu));

位段

在结构体中以位为单位的结构体成员,称之为位段 或者位域

注意: 不能对位域元素取地址

struct data
{
/* 16 位表示的是2个字节*/
 unsigned int a:2; /* :后面添加位数*/
 unsigned int b:6;
 unsigned int c:4;
 unsigned int d:4;
 unsigned int i; /*什么都没有添加表示以字节为位*/
};

对于位段进行赋值时,不能超过位段的最大值
例如 位数时2  则最大值时2的二次方-1   3

位段的类型必须是整型或者字符型
位段不能跨单元进行存储

位段的长度不能超过储存单元的长度
例如:char最大的储存单元是8 因此不能超过8
int 最大储存单元是32       因此不能超过32

struct stu
{
/* 由于使用了长度0的位段,其作用是让下一个位段在下一个存储单元进行存储*/
 unsigned char a:3;
 unsigned char b:4;
 unsigned char c:0;
 
 unsigned char d:3;  //在下一个单元进行存取
 
};

共用体

共用体 只需要把struct 转换成 union 就可以进行使用

共用体:在进行某种算法的时候,需要使用几种不同类型的变量存放在同一内存中,几个变量使用的内存相互重叠。
这种几种不同的变量占用同一内存空间的结构,在C语言中,被称为共用体

使用最大的字节数作为共用体的大小

共用体的特点
1)使用共用体变量的目的是希望用同一个内存段存放几种不同类型的数据,但请注意,在每一个瞬间只能存放其中一种,而不是同时存放几种;
2)能够访问的是共用体变量中最后一次被赋值的成员,在对一个新的成员赋值后原有的成员就失去作用。(覆盖)
3)共用体变量的地址和它各成员的地址都是同一个地址;
4)不能对共用体变量名赋值;不能企图引用变量名来得到一个值;不能在定义共用体变量时对它初始化;不能用共用体变量名作为函数参数。
5)和第二条相同 上一次初始化赋值,会被下一次的初始化所代替

#include <stdio.h>
#include <stdlib.h>
union stu
{
 int a;
 int b;
 char x;
};
int main()
{
	union stu xiaoming;
    xiaoming.a=100;
    xiaoming.b=120;
    xiaoming.x=62;
    printf("%d %d %d\n",xiaoming.a,xiaoming.b,xiaoming.x);
	system("pause");
	return 0;
}

在这里插入图片描述

枚举类型

枚举元素是一个常量

将变量的值一一的列举出来,变量的值只限于列出来的值的范围之内

1.枚举类型的定义方式
enum 枚举类型名{
  枚举值列表
};
枚举值表中应该列出所有可用值,也成为枚举元素

枚举变量只能取值 枚举值列表的值

2.枚举变量的使用
//加密类型
/* 使用的esp8266在stm32的程序中的*/
typedef enum{
	Multiple_ID_0 = 0,
	Multiple_ID_1 = 1,
	Multiple_ID_2 = 2,
	Multiple_ID_3 = 3,
	Multiple_ID_4 = 4,
	Single_ID_0 = 5,
} ENUM_ID_NO_TypeDef;

ENUM_AP_PsdMode_TypeDef enunPsdMode=Single_ID_0;//进行赋值使用

/* 最开始没有进行赋值 会默认是0  依次类推 */
typedef enum{
  STA,
  AP,
  STA_AP  
} ENUM_Net_ModeTypeDef;

/* 这样的执行结果是xx=4 yy=5 zz=4 qq=5*/
enum stu{
ss=3,xx,yy,zz=4,qq
};
/* */
;