download:玩转N种企业级解决方案,笑傲分布式开发

分布式:程序员永恒的命题。廖师兄重磅推出全网稀缺的Java分布式专题课,传授分布式修炼秘籍,带你构建完善的分布式知识体系,助你“硬技能+软实力”更上一层。课程包含分布式ID、分布式Session、分布式任务调度、分布式限流、分库分表、分布式事务六大专题,案例涵盖用户、报表、秒杀、订单等经典场景,企业常用分布式实战案例&解决方案,完整打包给你!

适合人群
Java工程师
对分布式感兴趣的同学
技术储备要求
熟悉SpringBoot / 熟悉Http协议
熟悉Mysql / 熟悉Docker
了解Redis
struct bs{
unsigned m;
unsigned n: 4;
unsigned char ch: 6;
};
:后面的数字用来限定成员变量占用的位数。成员 m 没有限制,依据数据类型即可推算出它占用 4 个字节(Byte)的内存。成员 n、ch 被:后面的数字限制,不能再依据数据类型计算长度,它们分别占用 4、6 位(Bit)的内存。

n、ch 的取值范围十分有限,数据略微大些就会发作溢出,请看下面的例子:

#include <stdio.h>
int main(){
struct bs{
unsigned m;
unsigned n: 4;
unsigned char ch: 6;
} a = { 0xad, 0xE, '$'};
//第一次输出
printf("%#x, %#x, %c\n", a.m, a.n, a.ch);
//更改值后再次输出
a.m = 0xb8901c;
a.n = 0x2d;
a.ch = 'z';
printf("%#x, %#x, %c\n", a.m, a.n, a.ch);
return 0;
}
运转结果:
0xad, 0xe, $
0xb8901c, 0xd, :

关于 n 和 ch,第一次输出的数据是完好的,第二次输出的数据是残缺的。

第一次输出时,n、ch 的值分别是 0xE、0x24('$' 对应的 ASCII 码为 0x24),换算成二进制是 1110、10 0100,都没有超出限定的位数,可以正常输出。

第二次输出时,n、ch 的值变为 0x2d、0x7a('z' 对应的 ASCII 码为 0x7a),换算成二进制分别是 10 1101、111 1010,都超出了限定的位数。超出局部被直接截去,剩下 1101、11 1010,换算成十六进制为 0xd、0x3a(0x3a 对应的字符是 :)。

C言语规范规则,位域的宽度不能超越它所依附的数据类型的长度。浅显地讲,成员变量都是有类型的,这个类型限制了成员变量的最大长度,:后面的数字不能超越这个长度。

例如上面的 bs,n 的类型是 unsigned int,长度为 4 个字节,共计 32 位,那么 n 后面的数字就不能超越 32;ch 的类型是 unsigned char,长度为 1 个字节,共计 8 位,那么 ch 后面的数字就不能超越 8。

我们能够这样以为,位域技术就是在成员变量所占用的内存当选出一局部位宽来存储数据。

C言语规范还规则,只要有限的几种数据类型能够用于位域。在 ANSI C 中,这几种数据类型是 int、signed int 和 unsigned int(int 默许就是 signed int);到了 C99,_Bool 也被支持了。

关于C言语规范以及 ANSI C 和 C99 的区别,我们已在付费教程《C言语的三套规范:C89、C99和C11》中停止了解说。

但编译器在详细完成时都停止了扩展,额外支持了 char、signed char、unsigned char 以及 enum 类型,所以上面的代码固然不契合C言语规范,但它仍然可以被编译器支持。

位域的存储
C言语规范并没有规则位域的详细存储方式,不同的编译器有不同的完成,但它们都尽量紧缩存储空间。

位域的详细存储规则如下:
1) 当相邻成员的类型相同时,假如它们的位宽之和小于类型的 sizeof 大小,那么后面的成员紧邻前一个成员存储,直到不能包容为止;假如它们的位宽之和大于类型的 sizeof 大小,那么后面的成员将重新的存储单元开端,其偏移量为类型大小的整数倍。

以下面的位域 bs 为例:

#include <stdio.h>
int main(){
struct bs{
unsigned m: 6;
unsigned n: 12;
unsigned p: 4;
};
printf("%d\n", sizeof(struct bs));
return 0;
}
运转结果:
4

m、n、p 的类型都是 unsigned int,sizeof 的结果为 4 个字节(Byte),也即 32 个位(Bit)。m、n、p 的位宽之和为 6+12+4 = 22,小于 32,所以它们会挨着存储,中间没有缝隙。

sizeof(struct bs) 的大小之所以为 4,而不是 3,是由于要将内存对齐到 4 个字节,以便进步存取效率,这将在《C言语内存精讲》专题的《C言语内存对齐,进步寻址效率》一节中细致解说。

假如将成员 m 的位宽改为 22,那么输出结果将会是 8,由于 22+12 = 34,大于 32,n 会重新的位置开端存储,相对 m 的偏移量是 sizeof(unsigned int),也即 4 个字节。

假如再将成员 p 的位宽也改为 22,那么输出结果将会是 12,三个成员都不会挨着存储。

2) 当相邻成员的类型不同时,不同的编译器有不同的完成计划,GCC 会紧缩存储,而 VC/VS 不会。

请看下面的位域 bs:

#include <stdio.h>
int main(){
struct bs{
unsigned m: 12;
unsigned char ch: 4;
unsigned p: 4;
};
printf("%d\n", sizeof(struct bs));
return 0;
}
在 GCC 下的运转结果为 4,三个成员挨着存储;在 VC/VS 下的运转结果为 12,三个成员依照各自的类型存储(与不指定位宽时的存储方式相同)。

m 、ch、p 的长度分别是 4、1、4 个字节,共计占用 9 个字节内存,为什么在 VC/VS 下的输出结果却是 12 呢?这个疑问将在《C言语和内存》专题的《C言语内存对齐,进步寻址效率》一节中为您解开。

3) 假如成员之间交叉着非位域成员,那么不会停止紧缩。例如关于下面的 bs:

struct bs{
unsigned m: 12;
unsigned ch;
unsigned p: 4;
};
在各个编译器下 sizeof 的结果都是 12。

经过上面的剖析,我们发现位域成员常常不占用完好的字节,有时分也不处于字节的开头位置,因而运用&获取位域成员的地址是没有意义的,C言语也制止这样做。地址是字节(Byte)的编号,而不是位(Bit)的编号。

无名位域
位域成员能够没有称号,只给出数据类型和位宽,如下所示:

struct bs{
int m: 12;
int : 20; //该位域成员不能运用
int n: 4;
};

©著作权归作者所有:来自51CTO博客作者mb603317150b7a1的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 软件架构-分布式系列并发编程Lock锁和Tools限制
  2. 《数据持久化与鸿蒙的分布式数据管理能力》直播课答疑和PPT分享
  3. 一体型遥控终端单元RTU-R85G 及分布式DTU配电自动化间隔单元(主
  4. 容器云平台No.6~企业级分布式存储Ceph~v14.2.10
  5. c++ this
  6. Hadoop3.x入门:完全分布式Hadoop集群安装部署
  7. 分布式文件系统监控
  8. MYSQL MGR 从入门到精通 02
  9. 分布式数据库中间件设想

随机推荐

  1. Android(安卓)之 使用File类在SD卡中读取
  2. Android系统架构-----Android的系统体系
  3. Android studio学习之TextView、EditText
  4. Android软件工程师之不归路
  5. RN系列:Android原生与RN如何交互通信
  6. Android 4高级编程(第3版) 试读
  7. Android开发UI之android:gravity / andro
  8. Android 中文API合集(3)(83篇)(chm格式)
  9. 关于Android的selector小用法
  10. Android菜单详解——理解android中的Menu