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)--- 共用体,位域深入的更多相关文章

  1. Go学习笔记07-结构体与方法

    Go学习笔记07-结构体与方法 Go语言 面向对象 结构的定义与创建 面向对象 Go语言只支持封装,不支持继承和多态. Go语言中只有struct,即结构体:没有class. 结构的定义与创建 pac ...

  2. C语言学习笔记10-结构体、枚举、联合体

    C语言学习笔记10-结构体.枚举.联合体    待传

  3. 《PHP7底层设计与源码实现》学习笔记2——结构体对齐

    书里给了一段代码,假如有个结构体如下: struct test {     char a;     int b;     long c;     void* d;     int e;     cha ...

  4. C语言笔记 09_共用体&typedef&输入|输出

    共用体 共用体允许您在相同的内存位置存储不同的数据类型.您可以定义一个带有多成员的共用体,但是任何时候只能有一个成员带有值.共用体提供了一种使用相同的内存位置的有效方式. 定义共用体 为了定义共用体, ...

  5. Object C学习笔记20-结构体

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  6. C#学习笔记之结构体

    1.概述 结构是一种与类相似的数据类型,不过它较类更为轻量,一般适用于表示类似Point.Rectangle.Color的对象.基本上结构能办到的类全都能办到,但在某些情况下使用结构更为合适,后面会有 ...

  7. Objective-C RunTime 学习笔记 之 基础结构体

    1.OC 运行期常用对象结构体 基本的结构体定义 typedef objc_class Class; /* 类 */ typedef objc_object *id; /* 各种类型,只要第一个字段为 ...

  8. Object C学习笔记20-结构体(转)

    在学习Object C中的过程中,关于struct的资料貌似非常少,查阅了C方面的资料总结了一些学习心得! 一. 定义结构 结构体是一种数据类型的组合和数据抽象.结构体的定义语法如下: struct ...

  9. contiki学习笔记---process结构体

    process,字面意义,进程,看看它的结构 struct process { struct process *next; #if PROCESS_CONF_NO_PROCESS_NAMES #def ...

  10. c语言学习笔记之结构体存储

    今天讲讲结构体存储问题 首先,结构体简单说是对不同类型的封装,一开始我们可能会想结构体在内存中的存储的大小是直接元素的和 例如 我们可能会觉得是 结构体大小=int(4个字节)+ short(2个字节 ...

随机推荐

  1. jenkins构建找不到python依赖

    最近在搞jenkins自动构建,遇到这样一个问题,我装的python相关的依赖在X用户下,但是jenkins在root下运行的,所以找不到相关的import 1. 执行pip freeze,会打印相关 ...

  2. bay——Oracle RAC环境下ASM磁盘组扩容.docx

    https://www.cnblogs.com/polestar/p/10115263.html Oracle RAC环境下ASM磁盘组扩容 生产环境注意调整以下参数: +++++++++++++++ ...

  3. Android程序中,内嵌ELF可执行文件-- Android开发C语言混合编程总结

    前言 都知道的,Android基于Linux系统,然后覆盖了一层由Java虚拟机为核心的壳系统.跟一般常见的Linux+Java系统不同的,是其中有对硬件驱动进行支持,以避开GPL开源协议限制的HAL ...

  4. rasa结合kashgari训练数据时,out of memory错误

    这两天新搬办公室,网络不好用,将就了.博客园也上不了,github也上不了了,工作效率降低不少.今天遇到同事使用rasa用机器人项目的问题,一个4核的Tesla K80 GPU,性能照说不差,但一运行 ...

  5. 异常类的构建——顶层父类Exception的实现

    异常类构建异常的类型可以是自定义类类型对于类类型异常的匹配依旧是从上到下严格的匹配赋值兼容性原则在异常匹配中依然适用一般而言-匹配子类异常的catch放在上部-匹配父类异常的catch放在下部 现代C ...

  6. 201871010128-杨丽霞《面向对象程序设计(java)》第一周学习总结

    201871010128-杨丽霞<面向对象程序设计(java)>第一周学习总结 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这 ...

  7. poj 2431 Expedition 贪心 优先队列 题解《挑战程序设计竞赛》

    地址 http://poj.org/problem?id=2431 题解 朴素想法就是dfs 经过该点的时候决定是否加油 中间加了一点剪枝 如果加油次数已经比已知最少的加油次数要大或者等于了 那么就剪 ...

  8. C++ class 内的 () 重载示例

    #include <iostream> // overloading "operator () " outside class //////////////////// ...

  9. git必知必会

    1. Git 配置 --system #系统级别--global #用户全局--local #单独一个项目 git config --global user.name "xxxx" ...

  10. npm 命令 --save 和 --save-dev 的区别

    回顾 npm install 命令 我们在使用 npm install 安装模块的模块的时候 ,一般会使用下面这几种命令形式: 1 2 3 4 5 6 7 npm install moduleName ...