C学习笔记(6)--- 共用体,位域深入
1.共用体(Union):
共用体是一种特殊的数据类型,允许您在相同的内存位置存储不同的数据类型。您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值。共用体提供了一种使用相同的内存位置的有效方式。
为了定义共用体,您必须使用 union 语句,方式与定义结构类似。
例子:
union Data {
int i;
float f;
char str[20];
} data;
这意味着一个变量(相同的内存位置)可以存储多个多种类型的数据。您可以根据需要在一个共用体内使用任何内置的或者用户自定义的数据类型。共用体的占用的内存大小由最大的变量决定---这个例子里面就是字符串(char str[20]),占用20个字节内存。
为了访问共用体的成员,我们使用成员访问运算符(.)。 但是和结构体不一样,由于共用体本质上是一个内存位置,所以会导致在同一时间里只能有一个值占用内存位置。
比如:
data.i = 10;
data.f = 220.5;
strcpy( data.str, "C Programming");
printf( "data.i : %d\n", data.i);
printf( "data.f : %f\n", data.f);
printf("data.str : %s\n", data.str);
打印(printf)这个三个值,前两个值都会损坏,因为内存位置被赋给了str.
但是假如是:
data.i = 10;
printf( "data.i : %d\n", data.i);
data.f = 220.5;
printf( "data.f : %f\n", data.f);
strcpy( data.str, "C Programming");
printf( "data.str : %s\n", data.str);
每次内存被占用之后都打印了出来,然后又重新赋值,所以不会造成损坏。
共用体作用:
节省内存,有两个很长的数据结构,不会同时使用,比如一个表示老师,一个表示学生,如果要统计教师和学生的情况用结构体的话就有点浪费了!用共用体的话,只占用最长的那个数据结构所占用的空间,就足够了!
共用体应用场景:
通信中的数据包会用到共用体:因为不知道对方会发一个什么包过来,用共用体的话就很简单了,定义几种格式的包,收到包之后就可以直接根据包的格式取出数据。
2.位域 Bit field(深入):
假设我们需要一个结构体只储存一个固定长度的值(比如说 1,0 这种来代表true/false --- 0001只需要一个bit)的,如果正常去定义,需要两个 int (每个4字节 Byte,一共 8 Byte)。C 语言提供了一种更好的利用内存空间的方式。如果您在结构内使用这样的变量,您可以定义变量的宽度来告诉编译器,您将只使用这些字节Byte。
定义例子:
struct {
unsigned int widthValidated : 1;
unsigned int heightValidated : 1;
} status;
如上,status 变量将占用 4 个字节(byte)的内存空间,但是只有 2 位(bit)被用来存储值,意思就是说这两个成员共用了一个int的内存空间(都是同类型)。
如果您用了 32 个变量,每一个变量宽度为 1 位,那么 status 结构将使用 4 个字节,但只要您再多用一个变量,如果使用了 33 个变量,那么它将分配内存的下一段来存储第 33 个变量,这个时候就开始使用 8 个字节。
Age.age = 7;
printf( "Age.age : %d\n", Age.age );
Age.age = 8; // 二进制表示为 1000 有四位,超出
printf( "Age.age : %d\n", Age.age );
output :
Age.age : 7
Age.age : 0
这个结果还会伴随着警告。
sub:(来自上章)
1.一个位域存储在同一个字节中,如一个字节所剩空间不够存放另一位域时,则会从下一单元起存放该位域。也可以有意使某位域从下一单元开始。
2.由于位域不允许跨两个字节,因此位域的长度不能大于一个字节的长度,也就是说不能超过8位二进位。如果最大长度大于计算机的整数字长,一些编译器可能会允许域的内存重叠,另外一些编译器可能会把大于一个域的部分存储在下一个字中。
3.位域可以是无名位域,这时它只用来作填充或调整位置。无名的位域是不能使用的.
4.位域在本质上就是一种结构类型,不过其成员是按二进位分配的。
5.结构体变量的首地址能够被其最宽基本类型成员的大小所整除。
6.结构体每个成员相对于结构体首地址的偏移量(offset)都是成员大小的整数倍,如有需要编译器会在成员之间加上填充字节(internal adding)。即结构体成员的末地址减去结构体首地址(第一个结构体成员的首地址)得到的偏移量都要是对应成员大小的整数倍。
7.
超出范围并不是直接丢弃,而是保留对应的 3 位的值。
比如 8 是 00001000,按照位域,对应 3 位的值是 000,所以打印结果是 0;
但是 9 是 00001001,按照位域,对应 3 位的值是 001,所以打印结果是 1;
同理 10 是 00001010,按照位域,对应 3 位的值是 010,所以打印结果是 2;
引用:
https://www.runoob.com/cprogramming/c-unions.html
https://www.runoob.com/cprogramming/c-bit-fields.html
C学习笔记(6)--- 共用体,位域深入的更多相关文章
- Go学习笔记07-结构体与方法
Go学习笔记07-结构体与方法 Go语言 面向对象 结构的定义与创建 面向对象 Go语言只支持封装,不支持继承和多态. Go语言中只有struct,即结构体:没有class. 结构的定义与创建 pac ...
- C语言学习笔记10-结构体、枚举、联合体
C语言学习笔记10-结构体.枚举.联合体 待传
- 《PHP7底层设计与源码实现》学习笔记2——结构体对齐
书里给了一段代码,假如有个结构体如下: struct test { char a; int b; long c; void* d; int e; cha ...
- C语言笔记 09_共用体&typedef&输入|输出
共用体 共用体允许您在相同的内存位置存储不同的数据类型.您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值.共用体提供了一种使用相同的内存位置的有效方式. 定义共用体 为了定义共用体, ...
- Object C学习笔记20-结构体
在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...
- C#学习笔记之结构体
1.概述 结构是一种与类相似的数据类型,不过它较类更为轻量,一般适用于表示类似Point.Rectangle.Color的对象.基本上结构能办到的类全都能办到,但在某些情况下使用结构更为合适,后面会有 ...
- Objective-C RunTime 学习笔记 之 基础结构体
1.OC 运行期常用对象结构体 基本的结构体定义 typedef objc_class Class; /* 类 */ typedef objc_object *id; /* 各种类型,只要第一个字段为 ...
- Object C学习笔记20-结构体(转)
在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...
- contiki学习笔记---process结构体
process,字面意义,进程,看看它的结构 struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #def ...
- c语言学习笔记之结构体存储
今天讲讲结构体存储问题 首先,结构体简单说是对不同类型的封装,一开始我们可能会想结构体在内存中的存储的大小是直接元素的和 例如 我们可能会觉得是 结构体大小=int(4个字节)+ short(2个字节 ...
随机推荐
- 用while循环写一个简单的猜数字游戏
import random #练习:模拟猜数字的游戏 """ 计算机出一个1~100之间的随机数由人来猜 计算机根据人猜的数字分别给出 大一点/小一点/猜中了 的提示 & ...
- Sublime Text 3如何关闭自动更新
1.Preferences -> Settings-User 2.插入下面代码:"update_check": false 如果有其他的设置,用逗号隔开,然后保存 3.Pre ...
- 微服务SpringCloud项目架构搭建入门
Spring的微服务框架SpringCloud受到众多公司欢迎,给大家带来一篇框架搭建入门.本次采用的版本是Spring Cloud版本为Finchley.RELEASE. 一.SpringCloud ...
- 使用Runtime的objc_msgSend实现模型和字典的互转
一.介绍 模型转字典,字典转模型,这是开发中最基本的功能.系统类中提供了一个setValuesForKeysWithDictionary方法来实现字典转模型,至于模型转字典,这个就需要使用runtim ...
- PHPer的项目RESTful API设计规范是怎样的?
RESTful 是目前最流行的 API 设计规范,用于 Web 数据接口的设计. 什么是RESTful RESTful是一种软件设计风格, 主要用于客户端与服务端交互的软件. 一般来说RESTful ...
- linux 常用配置
linux mysql yum 配置 https://blog.csdn.net/wngpenghao/article/details/78862923 linux jdk1. yum install ...
- Java 泛型示例 - 泛型方法,类,接口
Java Genrics 是 Java 5 中引入的最重要的功能之一. 如果您一直在使用Java Collections并使用版本 5 或更高版本,那么我确定您已经使用过它. Java 中具有集合类的 ...
- POJ 1724 (分层图最短路)
### POJ 1724 题目链接 ### 题目大意: 给你 N 个点 ,M 条有向路,走每条路需要花费 C 元,这段路的长度为 L . 给你 K 元,问你能否从 1 走到 N 点且花费不超过 K 元 ...
- @PostConstruct - 静态方法调用IOC容器Bean对象
需求:工具类里面引用IOC容器Bean,强迫症患者在调用工具类时喜欢用静态方法的方式而非注入的方式去调用,但是spring 不支持注解注入静态成员变量. 静态变量/类变量不是对象的属性,而是一个类的属 ...
- WPF后台代码实现TextBlock滚动条
方法一: 常规的WPF操作: <ScrollViewer Width=" VerticalScrollBarVisibility="Auto" Horizontal ...