当前位置: 首页 > news >正文

C语言自定义类型讲解:结构体,枚举,联合(2)

🐵本篇文章将会对位段、枚举和联合的相关知识进行讲解


1. 位段📚

1.1 什么是位段

位段的声明和结构体类似,但是有两点不同:

1.位段的成员必须是int,unsigned int,signed int (C99之后也可以是其他成员,但一般是int, char)

2.位段的成员的后面都有一个冒号和一个数字,代表该成员所占的比特位

假如A是一个普通的结构体,那么此时A的大小为16个字节,那么位段A的大小是多少?

struct A
{int a : 2;int b : 5;int c : 10;int d : 30;
};
printf("%zd\n", sizeof(struct A));

得到的结果为8,可以看出位段相比于结构体更能节省空间,那位段是怎么分配内存空间的,为什么A的大小是8个字节?

1.2 位段的内存分配

位段在空间上按照4个字节(int)或一个字节(char)为单位来开辟的,也就是当位段成员主要是int时,它会先开辟4个字节,当不够用时会再开辟4个字节;当位段成员主要是char时,它会先开辟1个字节,当不够用时会再开辟1个字节

除此之外,位段还有许多跨平台问题:

1. int位段究竟是无符号unsigned int还是有符号signed int是不确定的

2. int位段的最大位段数是不确定的,因为在16位机器上int占2个字节,在32位机器上int占4个字节

3. 位段成员在内存中是从左到右分配还是从右到左分配是不确定的,比如还是以上题为例,由于位段成员主要是int类型,所以位段在空间上按4个字节为单位来开辟的,先开辟4个字节:

4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的

比如char位段,先开辟一个字节,a占6个比特位,b占4个比特位

下面以一个例题为例:

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

2. 枚举📚

枚举就是一一列举

2.1 枚举的定义

enum Color
{RED,GREEN,BLUE
};

每一个枚举常量都有对应的值,第一个枚举常量的默认值为0,之后依次递增1,在上述代码中枚举常量RED的值为0,GREEN为1,BLUE为2

enum Color
{RED,GREEN,BLUE
};int main()
{printf("%d", RED); //打印结果为0return 0;
}

我们也可以修改默认值

enum Color
{RED = 3,GREEN,BLUE
};

这样RED的值就变成了3,GREEN和BLUE也依次变为4和5

2.1 枚举的使用

enum Color
{RED,GREEN = 5,BLUE
};int main()
{enum Color clr = GREEN;//给枚举类型的变量赋值时要用枚举常量clr = 6; //这种形式的代码在vs的.c文件中不会报错,这是因为vs的.c文件对类型检查不够严格,当把.c文件改为.cpp文件时,程序就会报错,所以不建议这样写代码return 0;
}

3. 联合📚

3.1 联合的定义

联合体(共用体)也是一种自定义类型,它也包含一系列的成员,它的特征是这些成员共用同一空间

union un
{char c;int i;
};int main()
{union un u; //创建联合体变量printf("%p\n", &u); //求变量的地址printf("%p\n", &u.c); printf("%p\n", &u.i); //求成员的地址return 0;
}

有打印结果可以看出联合体的内部成员共用同一块空间;

深度剖析数据在内存中的存储中讲解过大小端存储模式,当时写过判断大小端存储模式的代码:

int check_sys()
{int a = 1;return *(char*)&a; //判断该数据的第一个字节是多少
}int main()
{int ret = check_sys();if (ret == 1){printf("小端存储\n");}else{printf("大端存储\n");}return 0;
}

同样我们也可以用联合实现判断大小端的功能

int check_sys()
{union un{char c;int i;}u;u.i = 1;return u.c;
}

3.2 计算联合的大小

联合体的成员共用同一块内存空间,一个联合体变量的大小至少是其最大成员的大小,因为当最大成员的大小不是最大对齐数的整数倍时就要对齐到最大对齐数的整数倍处

union un
{char c[5];int i;
}u;int main()
{printf("%zd", sizeof(u)); //结果为8return 0;
}

上述代码中c的对齐数是1,i的对齐数是4,所以最大对齐数是4,而char c[5]的大小是5个字节,所以要再浪费3个字节对齐到4的倍数也就是8个字节


🙉至此,有关结构体、位段、枚举和联合的知识全部讲解完毕;之后会讲解动态内存管理

http://www.lryc.cn/news/175821.html

相关文章:

  • AI编程助手 Amazon CodeWhisperer 全面解析与实践
  • 利用EXCEL进行XXE攻击
  • 芯片验证就是一次旅行
  • Java深入理解线程的三大特性
  • 2025快手校招面试真题汇总及其解答(二)
  • PHP生成带中文的图片
  • java框架-Dubbo
  • Vue+iview 组件中通过v-for循环动态生成form表单进行表单校验
  • sns.load_dataset(“iris“)报错原因探究+解决办法
  • python回文素数
  • 纽扣电池16CRF1700.15,16CFR1700.20,ANSI C18.3M如何申请?
  • 10.12广州见 | 第十六届智慧城市大会报名通道全面开启
  • 2023-油猴(Tampermonkey)脚本推荐
  • 某度sign参数逆向
  • 【选型】JAVA生成PPT及选型
  • LPA*算法图文详解
  • 【Unity的HDRP渲染管线下实现好用的GUI模糊和外描边流光效果_Blur_OutLine_案例分享(内附源码)】
  • 电脑D盘格式化会有什么影响?电脑D盘格式化了怎么恢复数据
  • 【Spring】多环境切换
  • python经典百题之求10000之内的素数
  • ROS2 从头开始:第 5 部分 - 并发、执行器和回调组
  • 笔试强训Day3
  • 软考软件设计师-存储管理-文件管理-计算机网络(中
  • Vue3的学习
  • 什么是Peppol ID?如何创建?
  • Spring注解大揭秘:@Component、@Service、@Repository详解
  • Innodb底层原理与Mysql日志机制
  • 浅谈大数据背景下用户侧用电数据在电力系统的应用与发展分析
  • 20230919在WIN10下使用python3将PDF文档转为DOCX格式的WORD文档
  • PCR检测试剂——博迈伦