位段-枚举-联合体

文章介绍了C语言中位段的概念,包括其节省内存的特性,但指出位段在不同字节序机器间的移植性问题。接着讨论了枚举的使用和优点,如增强代码可读性和类型检查。最后,解释了联合体的工作原理,即所有成员共享同一块内存空间,以及联合体大小的计算规则。
摘要由CSDN通过智能技术生成

一、位段

位段是什么?

位段是结构体所能实现的一种功能

位段是什么样的?

在结构体的基础上加上了以下两种特性

1.位段的成员必须是 int、unsigned int 或signed int 。

2.位段的成员名后边有一个冒号和一个数字

例如:

struct A
{
    int _a:2;    //位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型
    int _b:5;
    int _c:10;
    int _d:30;
};

接下来我们细细对位段进行学习

首先就是这个位段占多少存储空间

位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

在此之前我们学习的结构体都是一次申请多个字节,甚至算上对齐,会消耗一部分的空间,那么有一种想法就是,我们能不能把每一位划分成几个段来使用,以达到更高的利用

例如

struct S
{
    char a:3;
    char b:4;
    char c:5;
    char d:4;
};
    struct S s = {0};
    s.a = 10;
    s.b = 12;
    s.c = 3;
    s.d = 4;

按照上述来说,位段对于我们来说是非常节省内存的一件事,那使用的应该会很多吧。

但是事实却不是如此,在如今互联网加移动应用及数据交互的大环境下,应用及数据讲究可移植性,因为我们所使用的硬件机器分为大端字节序机器和小端字节序机器,简而言之就是正着放和倒着放(只为方便理解,详情请客官移步(35条消息) 剖析数据在内存中的存储(C语言)_weielite的博客-CSDN博客

这就导致一个问题,假设两台信息交互的设备不是同种字节序的机器,还能读出相同的数据吗?

例如: 十进制的23:在大端字节序的机器中是这样存储的 0001 0111

在小端字节序的机器中是这样存储的 1101 0100

那么如果将小端机器的数据按找大端机器的读取方式读取结果可想而知,一定是不正确的

这也就导致了位段设计的数据在自身设备上固然可以节省内存,但是对移植性则是致命的打击

总结如下:

1.int 位段被当成有符号数还是无符号数是不确定的。

2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机

器会出问题。

3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是

舍弃剩余的位还是利用,这是不确定的

二、枚举

枚举:简单的说就是一一列举

看个例子就明白啦

enum Sex//性别,有男有女和保密
{
    MALE,//0
    FEMALE,//1
    SECRET//2
};

enum Color//颜色,有红,有绿,有蓝
{
    RED=1,
    GREEN=2,
    BLUE=5
};

在上述代码中的两个例子中

enum Sex和enum Color都是枚举类型,而{ }中的内容都是枚举类型可能的取值,叫做枚举常量

这些取值是有值的,默认从0开始依次递增1,如enum Sex中的三个取值

也可以如enum Color中赋初值,那么每一个的值就为赋的值。

从这来看枚举类型很像#define几个值,相比之下我们为什么要选择枚举类型呢

枚举的优点:

1. 增加代码的可读性和可维护性

2. 和#define定义的标识符比较枚举有类型检查,更加严谨。

3. 防止了命名污染(封装)

4. 便于调试

5. 使用方便,一次可以定义多个常量

亲测使用起来真的很方便!

三、联合体

从名称上看也不难理解,所有成员公用一块空间

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

合至少得有能力保存最大的那个成员)

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);
//输出结果是11223355(在大端机器环境下),因为当两个成员共用同一块地址时
//整形i控制了从联合体地址开始的四个字节空间
//而char类型的c也是从联合体地址开始,但是只使用一个字节,所以也就只能改变一个字节的值

联合体大小计算

联合的大小至少是最大成员的大小。//可以理解为卧室最起码得放下一张床

当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍;

例如:

union Un1
{
    char c[5];
    int i;
};
union Un2
{
    short c[7];
    int i;
};

printf("%d\n", sizeof(union Un1));
//很显然第一个最大占用空间应当为5,但是第二个元素为4字节大小,那么这里un1的大小就应该为8
printf("%d\n", sizeof(union Un2));
//同理这里un2应当为16

今天的知识分享就到这里了,我们下会见!

点个赞再走呗

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值