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

C语言进阶——自定义类型——位段、枚举、联合

结构体


目录

一.   位段

1.概念

2.位段的内存分配

3.位段的跨平台问题

4.位段的应用

二.   枚举

1.枚举类型的定义

2.枚举的优点

3.枚举的使用

三.   联合(共用体)

1.联合类型的定义

​编辑

2.联合的特点

3. 联合大小的计算


一.   位段

1.概念

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

1.位段的成员必须是 int、unsigned int 、signed int或char(本质上也属于整形) 。

2.位段的成员名后边有一个冒号和一个数字,而这个数字表示的是所占的二进制位数

例如

struct A
{
    int _a:2;
    int _b:5;
    int _c:10;
    int _d:30;
};

2.位段的内存分配

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

后面的数字不能大于类型的大小

位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

int main()
{
    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;
    return 0;
}

我们就用上面这代码来研究一下位段是如何进行内存分配的

首先,每个字节都有8位 

 顺着来看一下,首先是a,首先写出10的补码  00001010,然后将前三位(010)截断放进去

 然后是b, 12的补码是00001100,将前四位(1100)截断放进去

然后是c,3的补码是00000011,将前五位(00011)放进去,但我们可以看到,这一个字节只剩下一位了,放不开五位,根据编译器的不同,有的会先存满这个字节,再存下一个字节,而有的会直接在下一个字节存储,而我使用的vs2022是第二种方式

 最后的d也一样

 最后就是这个样子

 int 也差不多


3.位段的跨平台问题

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

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

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

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


4.位段的应用



二.   枚举

枚举顾名思义就是一一列举,把可能的取值一一列举。在之前的学习中也大致的提到过

1.枚举类型的定义

enum Color
{
    RED,
    GREEN,
    BLUE
};

就是这么定义的

第一个取值默认为0,后面依次递增1,当然,我们可以改变任何位置的值,后面依旧是依次递增1


2.枚举的优点

枚举的优点:

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

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

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

4. 便于调试

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


3.枚举的使用

只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。

enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN;//right
clr = 5; //error


三.   联合(共用体)

1.联合类型的定义

联合也是一种特殊的自定义类型

这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)

例如

int main()
{
	union Un
	{
		char c;
		int i;
	};
	union Un un;
	printf("%p\n", &(un.i));
	printf("%p\n", &(un.c));
}

可以看到,两个成员的地址是相同的,这也就证实了成员是公用同一块空间的 


2.联合的特点

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

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



可以看到,在成员c改变时,i也会跟着改变

因此,我们也可以利用这一点来判断机器是大端还是小端

类似于上面,便是小端,而若是55223344,便是大端


3. 联合大小的计算

联合的大小至少是最大成员的大小。

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

第一点很好理解,毕竟联合的大小必须能够存放下每个成员

而第二点,举个例子

	union Un
	{
		int i;
		char c[5];
	};

这个联合,最大的成员大小应该是c的5个字节,而最大对齐数应该是4(int),这时,我们便需要进行对齐,大小则应该为8









 

相关文章:

  • 响应式与观察者模式
  • Codeforces Round #842 (Div. 2)
  • C/C++ - 从代码到可执行程序的过程
  • TypeScript类型 : any,unknown
  • Leetcode:501. 二叉搜索树中的众数(C++)
  • mysql数据库管理-服务器语句超时处理参数
  • 【Linux】工具使用
  • 从零备战蓝桥杯——动态规划(子序列篇)
  • React 学习笔记总结(八)
  • 基于FPGA的UDP 通信(三)
  • 用HTML写一个2023跨年动画代码(烟花+自定义文字+背景音乐+雪花+倒计时)
  • 聊聊VMware的三种网络模式
  • 终极 3D 图形工具包:Ab3d.PowerToys 10.2.X Crack
  • C++ 类和对象(三)
  • R语言实现牛顿插值
  •  D - 粉碎叛乱F - 其他起义
  • echarts花样作死的坑
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • iOS仿今日头条、壁纸应用、筛选分类、三方微博、颜色填充等源码
  • nodejs:开发并发布一个nodejs包
  • RedisSerializer之JdkSerializationRedisSerializer分析
  • Shell编程
  • vagrant 添加本地 box 安装 laravel homestead
  • Vultr 教程目录
  • 阿里云Kubernetes容器服务上体验Knative
  • 包装类对象
  • 关于List、List?、ListObject的区别
  • 利用jquery编写加法运算验证码
  • 漫谈开发设计中的一些“原则”及“设计哲学”
  • 如何胜任知名企业的商业数据分析师?
  • 使用 5W1H 写出高可读的 Git Commit Message
  • 使用common-codec进行md5加密
  • 算法-插入排序
  • 写代码的正确姿势
  • 新书推荐|Windows黑客编程技术详解
  • 阿里云ACE认证学习知识点梳理
  • ​力扣解法汇总1802. 有界数组中指定下标处的最大值
  • ​一文看懂数据清洗:缺失值、异常值和重复值的处理
  • # 数据结构
  • #define,static,const,三种常量的区别
  • #我与Java虚拟机的故事#连载04:一本让自己没面子的书
  • (vue)el-checkbox 实现展示区分 label 和 value(展示值与选中获取值需不同)
  • (zt)基于Facebook和Flash平台的应用架构解析
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (二)windows配置JDK环境
  • (附源码)springboot宠物医疗服务网站 毕业设计688413
  • (十三)Java springcloud B2B2C o2o多用户商城 springcloud架构 - SSO单点登录之OAuth2.0 根据token获取用户信息(4)...
  • (淘宝无限适配)手机端rem布局详解(转载非原创)
  • (转)Sql Server 保留几位小数的两种做法
  • (转载)虚幻引擎3--【UnrealScript教程】章节一:20.location和rotation
  • .NET 4 并行(多核)“.NET研究”编程系列之二 从Task开始
  • .NET CORE Aws S3 使用
  • .NET 发展历程
  • .NET 回调、接口回调、 委托
  • .考试倒计时43天!来提分啦!