当前位置 博文首页 > MOUYULOU的博客:自定义类型:结构体 枚举 联合体 那些你不知道

    MOUYULOU的博客:自定义类型:结构体 枚举 联合体 那些你不知道

    作者:[db:作者] 时间:2021-08-07 12:59

    自定义类型:结构体 枚举 联合体

    一.结构体

    结构体声明

    struct为结构体关键字,tag为结构体的标志,member-list为结构体成员列表,其必须列出其所有成员;variable-list为此结构体声明的变量。

    struct tag
    {
         member_list;
    }variable_list;
    

    描述一个学生

    struct stu
    {
          char name[20];//姓名
          int age;//年龄
          chae sex[5];//性别
    }//分号不能少
    

    特殊声明 在声明时可以不完全声明

    struct//省略掉了结构体标签
    {
         int a;
         char b;
    }x;
    

    结构体自引用

    strcut Node
    {
        int data;
        struct Node next;
    };//这样是否可行?那么sizeof(struct Node)是多少?
    

    显然上边这种方法无法计算sizeof(struct Node)是多少 下边是正确的自引用方式:

    strcut Node
    {
        int data;
        struct Node* next;
    };
    

    结构体变量的定义和初始化

    struct stu//声明结构体类型
    {
    	char nam[20];//姓名
    	int age;//年龄
    	char sex[5];//性别
    };
    int main()
    {
    	struct stu s1= { "zhangsan", 20, "nan" };//结构体初始化
    	printf("%s %d %s", s1.nam, s1.age, s1.sex);//访问结构体变量元素
    	return 0;
    }
    

    结构体内存对齐

    在这里插入图片描述
    为什么结果是12?是如何计算?
    首先我们先得掌握结构体对齐规则:
    1.第一个成员在与结构体变量偏移量为0的地址处
    2.其他成员变量对齐到某个数字(对齐数)的整数倍地址处
    对齐数=编译器默认的一个对齐数与该成员大小的较小值
    3.结构体总大小为最大对齐数的整数倍
    4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体整体的大小就是所有最大对齐数的整数倍
    在这里插入图片描述
    那么为什么存在结构体对齐?
    1.平台原因:不是所有硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据。
    2.性能原因:数据结构(尤其是栈)应该尽可能的在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要做两次访问,而对齐的内存访问仅需要访问一次。

    在设计结构体时我们既要满足对齐,又要节省空间,就需要让占用空间小的成员尽量集中在一起。
    修改默认对齐数

    #pragma pack(8)//修改默认对齐数为8
    

    位段

    什么是位段:1.位段的成员必须是 int unsigned int 或signed int
    2.位段的成员名后边有一个冒号和一个数字

    struct A
    {
         char a:3;
         char b:4;
         char c:5;
         char d:4;
    };
    

    A就是一个位段
    位段的内存分配
    1.位段的成员可以说int unsigned int signed int 或char类型
    2.位段的空间上是按照需要4字节(int)或者1字节(char)的方式来开辟的。
    3.位段涉及很多不确定因素,位段是不跨平台的。
    在这里插入图片描述
    为什么?
    在这里插入图片描述

    二.枚举

    枚举:把可能的取值列举出来

    枚举类型的定义

    enum sex//性别
    {
         male;
         female;
         secret;
    };
    

    这些可能取值都是有值的,默认从0开始,一次递增1,也可在定义是赋初值

    enum sex//性别
    {
         male=1;
         female=2;
         secret=4;
    };
    

    枚举的优点

    1.增加代码的可读性和可维护性
    2.和#define定义标识符比较枚举有类型检查,更加严谨
    3.防止命名污染
    4.便于调试
    5.使用方便,一次可以定义多个常量

    联合(共用体)

    联合类型的定义

    联合是一种特殊的自定义类型 这种类型定义变量包含一系列成员,特征是这些成员公用同一块空间

    //联合体类型声明
    union un
    {
         char c;
         int i;
    };
    //联合变量定义
    union Un un;
    //计算联合变量大小
    printf("%d\n",sizeof(un));
    

    联合的特点

    联合的成员共用同一块内存空间,一个联合变量的大小,至少是最大成员大小

    union Un
    {
    	int i;
    	char c;
    }un;
    int main()
    {
    	un.i = 0x11223344;
    	un.c = 0x55;
    	printf("%x\n", un.i);
    }
    

    在这里插入图片描述
    用联合体判断计算机的大小端存储

    int check_sys()//联合体大小端判断
    {
    	union U
    	{
    		char c;
    		int i;
    	}u1;
    	u1.i = 1;
    	return u1.c;
    }
    int main()
    {
    	int ret = check_sys();
    	if (1 == ret)
    		printf("小端\n");
    	else
    		printf("大端\n");
    	return 0;
    }
    

    联合大小的计算

    联合的大小至少是最大成员的大小
    当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。

    union Un1
    {
    	char c[5];
    	int i;
    };
    union Un2
    {
    	short c[7];
    	int i;
    };
    int main()
    {
    	printf("%d\n", sizeof(union Un1));
    	printf("%d\n", sizeof(union Un2));
    	return 0;
    }
    

    在这里插入图片描述

    cs