IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 位段,结构体+枚举+联合详解 -> 正文阅读

[数据结构与算法]位段,结构体+枚举+联合详解

位段

什么是位段

在C语言中有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可,基于这种特殊的存储,C语言又提供了一种叫做位域的数据结构。
在结构体定义时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域

位段的声明

位段的声明和结构类似但是有两个不同
e.g.
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字

struct bw{
    unsigned m;
    unsigned n: 4;
    unsigned char ch: 6;
}
struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};

关于位段的内存分配问题

学会了如何声明之后相信有很多小伙伴是不是在思考,这个东东到底在内存中占多少空间呢??这里我们不妨来讨论一下:

printf("%d\n", sizeof(struct A));

通过我们的编译器(vs2019)能得到如下得结果
在这里插入图片描述
到这里相信很多小伙伴就以及开始犯糊涂了,这个结构体按照内存对齐原则根据偏移量来计算的话(4+4+4+4)应该为16,为什么结果却为8呢?下面我们来了解一下位段的存储规则
位域的具体存储规则如下:

  1. 当相邻成员的类型相同时,如果它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能容纳为止;如果它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将从新的存储单元开始,其偏移量为类型大小的整数倍。
    通俗版:将上述规则简单通俗的说出来其实就是,在vs2019中位段冒号后面的数字决定这个变量类型所开辟出来的空间,变量将要占有的比特位,例如上面的 bw,n 的类型是 unsigned int,长度为 4 个字节,共计 32 位,那么 n 后面的数字就不能超过 32;ch 的类型是 unsigned char,长度为 1 个字节,共计 8 位,那么 ch 后面的数字就不能超过 8(图中所占空间为6bit)。

到这里就不难解释为什么是8而不是16了
struct A中有4个int 类型的变量,第一个int开辟出4个字节也就是32个bit,但是_a只占2个bit位,故_b占的5个bit也能够放入,_c所占10个bit也能够放入,到_c这一共放了17个bit,还剩下15个bit位,但是_d为30bit,显然放不进,故int _d向内存第二次申请4个字节的空间将30个bit全部放入,故最后的答案为8个字节!

结构体

——结构体,它就将不同类型的数据存放在一起,作为一个整体进行处理。

结构体的基础知识介绍

例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放。
在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员(Member)例如:

struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}//分号不能丢

接下来给大家介绍一下如何定义变量

#include <stdio.h>
int main() {
    struct {
        char* name;  //姓名
        int num;  //学号
        int age;  //年龄
        
    } stu1;
    //给结构体成员赋值
    stu1.name = "zhoumin";
    stu1.num = 1;
    stu1.age = 18;
    return 0;
}

枚举

在这里给大家介绍一下一个比较好玩的东西(枚举)enum

枚举类型的定义

他的主要系统结构和结构体非常类似,枚举数据表的值都是整数。第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。也可以人为设定枚举成员的值,从而自定义某个范围内的整数。

enum Day//星期
{
Mon,//打印为0
Tues,//1
Wed,//2
Thur,//3
Fri,//4
Sat,//5
Sun//6
};

以上定义的 enum Day就是一个是枚举类型,{}中的内容是枚举类型的可能取值,也叫 枚举常量

枚举的优点

这时候就有小伙伴要说了,我们可以使用 #define 定义常量,为什么非要使用枚举?
给大家介绍一下枚举的优点:

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

枚举的使用

使用枚举可以一次定义多个变量,如果使用#define的方式要从Mon开始一个一个去定义七遍,显得是不是有点太浪费时间了?下面运用了枚举来处理这事情瞬间就变得非常简单了,一次性全部定义了,是不是很香呢?

#include<stdio.h>
 
enum week {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
 
int main()
{
    printf("%d",Mon);
    return 0;
}

联合

联合类型的定义

联合也是一种特殊的自定义类型
结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
共用体也是一种自定义类型,可以通过它来创建变量,例如:

union data{
    int n;
    char ch;
    double f;
};
union data a, b, c;

联合的特点

联合的成员是共用同一块内存空间的,修改一个成员会影响其余所有成员,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。

# include<stdio.h>
int main() {

	union Un

	{
		int i;
		char c;
	};
	union Un un;
	// 下面输出的结果是一样的吗?
	printf("%d\n", &(un.i));
	printf("%d\n", &(un.c));
	//下面输出的结果是什么?
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);
	return 0;

}

在这里插入图片描述

联合大小的计算

1.联合体union特性
联合体所有成员变量共享内存,相对于联合体首地址偏移量都为0
同一时间只能存储1个被选择的变量,对其他成员变量赋值会覆盖原变量
2.联合体大小计算准则
联合体大小要至少能容纳最大的成员变量
联合体大小要是所有成员变量类型大小的整数倍

#include<stdio.h>
int main() {
	union Un1
	{
		char c[5];
		int i;
	};
	union Un2
	{
		short c[7];
		int i;
	};
	//下面输出的结果是什么?
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;

}

在清楚了上述的规则之后,我们来尝试运用一下,在union un1中我们可知至少要有51的空间,空间又必须为4的倍数,故sizeof(union un1)=8;再来看看union un2 中我们知道至少要有27的空间,空间又必须为4的倍数,故sizeof(union un2)=16;

在这里插入图片描述

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-10-07 14:04:31  更:2021-10-07 14:04:34 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:30:22-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码