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

C语言基础知识:位与位字段

目录

位与字节

比特

字节

对齐特性

位字段


位与字节

二进制数系统中,每个0或1就是一个位(bit),位是数据存储的最小单位。其中8 bit就称为一个字节(Byte)。计算机中的CPU位数指的是CPU一次能处理的最大位数,例如32位计算机的CPU一次最多能处理32位数据,计算机中的CPU位数也成为机器字长,和数据总线(CPU与内部存储器之间连接的用于传输数据的线的根数)的概念是统一的。

比特


1) 计算机专业术语,是信息量单位,是由英文BIT音译而来。二进制数的一位所包含的信息就是一比特,如二进制数0101就是4比特。
2)二进制数字中的位,信息量的度量单位,为信息量的最小单位。数字化音响中用电脉冲表达音频信号,“1”代表有脉冲,“0”代表脉冲间隔。如果波形上每个点的信息用四位一组的代码表示,则称4比特,比特数越高,表达模拟信号就越精确,对音频信号信号还原能力越强。

字节

1字节(byte) = 8 比特(bit) 

注:这个字节与比特的关系是规定的,记住就好,通用于任何场景,容易混淆的是字长和字节,字长指的是cpu一次性能够运算的数据的位数,不同的计算机可能不一样,但是字节这个概念是恒久不变的。

对齐特性

对齐指的是如何安排对象在内存中的位置。
_Alignof运算符给出了一个类型的对齐要求,在关键字_Aligof后面的圆括号中写上类型名即可:

size_t  d_align  = _Alignof(float);

假定d_align的值是4,意思float类型对象的对齐要求是4。较大的对齐值被称为stricter或stronger,较小的值被称为weaker.
可以使用_Alignas说明符指定一个变量或类型的对齐值,但是不应该要求该值小于基本对齐值。

_Alignas(double) char c1;
_Alignas(8) char c2;
unsigned char _Alignas(long double) c_arr[sizeof(long double)];

注意:

不同版本的要求不同,有的要求_Alignas(type)说明符在类型说明符的后面,有的在前面,无论哪一种都能够识别。

位字段

位字段(bit filed)是C语言中一种存储结构,不同于一般结构体的是它在定义成员的时候需要指定成员所占的位数。位字段是一个signed int或unsigned int类型变量中一组相邻的位(C99和C11新增了Bool类型的位字段)。位字段通过一个结构声明来建立,该结构声明为每个字段提供标签,并确定该字段的宽度。例如,下面的声明建立了4个1位的字段: 

struct {unsigned autfd : 1;unsigned bldfc : 1;unsigned undln : 1;unsigned itals : 1;
} prnt;

根据该声明,prnt包含了4个1位的字段。现在,可以通过普通的结构成员运算符(.)单独给这些字段赋值:

    prnt.itals=1;prnt.undln=0;prnt.bldfc=1;prnt.autfd=0;

下面查看一下prnt的值:

    char str[33];int* value=reinterpret_cast<int*>(&prnt);itoa(*value,str,2);printf("%d %d %d %d\n", prnt.autfd,prnt.bldfc,prnt.undln,prnt.itals);printf("sizeof(prnt) = %d\n",sizeof(prnt));printf("十进制: %d\n",prnt);printf("二进制: %032s\n",str);

输出的结果为:
0 1 0 1
sizeof(prnt) = 4
十进制: 10
二进制: 0000 0000 0000 0000 0000 0000 0000 1010

可以看出,prnt的大小为4个字节(unsigned int 或 signed int),通过prnt的结构成员可以设置和访问某些bit位的值。
带有位字段的结构提供了一种记录设置的方便途径。许多设置(如,字体的粗体或斜体)就是简单的二进制一。例如,开或关、真或假。如果只需要使用1位,就不需要使用整个变量。内含位字段的结构允许在一个存储单元中存储多个设置。
有时,某些设置也有多个选择,因此需要多位来表示。例如,可以使用如下代码:

struct{unsigned code1 : 2;unsigned code2 : 2;unsigned code3 : 8;
}prcode;

这里创建了两个2位的字段和一个8位的字段,可以这样赋值:

    prcode.code1=0;prcode.code2=3;prcode.code3=102;

但是要确保赋的值不超出字段可容纳的范围(下面会说明当超出范围时会发生什么事情)。

再次打印出prcode的内容

    int* value_prcode=reinterpret_cast<int*>(&prcode);itoa(*value_prcode,str,2);printf("%d %d %d\n",prcode.code1,prcode.code2,prcode.code3);printf("sizeof(prcode) = %d\n",sizeof(prcode));printf("十进制: %d\n",prcode);printf("二进制: %032s\n",str);

打印结果如下:
0 3 102
sizeof(prcode) = 4
十进制:1644
二进制:0000 0000 0000 0000 0000 0110 0110 1100

可以看出,prcode.code1对应于0-1比特位,数值为00,对应十进制为0;
prcode.code1对应于2-3比特位,数值为11,对应十进制为3;
prcode.code2对应于4-11比特位,数值为0110 0110,对应十进制为102。
因此,一个字段可以对应于多个比特位,且当使用结构字段赋值在可容纳的范围之内时,变量可以记录正确的值。

这里再讨论一些需要注意的问题。首先是,如果声明的总位数超过一个unsigned int类型的大小(4 bytes)时会发生什么事情?结果是会用到下一个unsigned int类型的存储位置。一个字段不允许跨越两个unsigned int之间的边界。编译器会自动移动跨界的字段,保持unsigned int的边界对齐。一旦发生这种情况,第1个unsigned int中会留下一个未命名的“洞”。例如:

struct{unsigned a : 4;unsigned b : 4;unsigned c : 4;unsigned d : 25;
}prlimit;

上面定义的位字段大小共37个bits,超过了一个unsigned int的范围,给prlimit的各结构成员赋值,并使用下面代码打印出prlimit所存储的内容:

    prlimit.a=0xF;prlimit.b=0;prlimit.c=0xF;prlimit.d=0x1FFFFFF;char str_1[33];char str_2[33];int* value_1=reinterpret_cast<int*>(&prlimit);int* value_2=reinterpret_cast<int*>(&prlimit)+1;itoa(*value_1,str_1,2);itoa(*value_2,str_2,2);printf("0x%x 0x%x 0x%x 0x%x \n",prlimit.a,prlimit.b,prlimit.c ,prlimit.d);printf("sizeof(prlimit) = %d\n",sizeof(prlimit));printf("二进制 0~31位: %032s\n",str_1);printf("二进制 32~63位: %032s\n",str_2);

输出的结果如下:
0xf 0x0 0xf 0x1ffffff
sizeof(prlimit) = 8
二进制 0-31位:0000 0000 0000 0000 0000 1111 0000 1111
二进制 32-63位:0000 0001 1111 1111 1111 1111 1111 1111

从输出的结果可以看出,首先,prlimit的大小为8个字节;其次,编译器强制prlimit.d字段发生边界对齐,即prlimit.d位于第二个unsigned int上,prlimit.c与prlimit.d之间会填充未命名的“洞”。

实际上,我们也可以人为的在结构体当中设置未命名的字段宽度来进行填充。使用一个宽度为0的未命名的字段迫使下一个字段与下一个整数对齐:

struct {unsigned field1 : 1;unsigned        : 2;unsigned field2 : 1;unsigned        : 0;unsigned field3 : 4;
} stuff;

 使用下面的代码输出stuff的内容:

    stuff.field1=1;stuff.field2=1;stuff.field3=0xf;char str_1[33];char str_2[33];int *value_1=reinterpret_cast<int*>(&stuff);int *value_2=reinterpret_cast<int*>(&stuff)+1;itoa(*value_1,str_1,2);itoa(*value_2,str_2,2);printf("sizeof(stuff) = %d\n",sizeof(stuff));printf("二进制 0-31位: %032s\n",str_1);printf("二进制 32-63位: %032s\n",str_2);

输出的结果为:
sizeof(stuff) = 8
二进制 0-31位:0000 0000 0000 0000 0000 0000 0000 1001
二进制 32-63位: 0000 0000 0000 0000 0000 0000 0000 1111

也就是说,在这里,stuff.field1和stuff.field2之间,有一个2位的空隙;stuff.field3被强迫与下一个整数对齐,存储到下一个unsigned int中。stuff的大小为8个字节。

最后讨论一个当赋值超出字段可容纳范围的问题。

struct {unsigned t1 : 2;unsigned t2 : 3;unsigned t3 : 4;
} test;int main(){test.t1=3;test.t3=0;test.t2=11;printf("%d %d %d\n",test.t1,test.t2,test.t3);int *value=reinterpret_cast<int*>(&test);char str[50];itoa(*value,str,2);printf("二进制:%032s\n",str);return 0;}

输出的结果为:
3 3 0
二进制:0000 0000 0000 0000 0000 0000 0000 1111

上述代码中,成员test.t2赋值的大小超出了容纳的范围。可以看到,t2赋值为11(二进制是1011),结果输出的值是3(二进制是011),即截断了超出的部分。同时也可以看到,超出的部分不会影响t3的值(不同平台不一样?网上有人说会覆盖超出的区域)。

最后需要说明的是,字段存储在一个int中的顺序取决于机器。在有些机器上,存储的顺序是从左往右的,而在另一些机器上,是从右往左的。另外,不同的机器中两个字段边界的位置也有区别。由于这些原因,位字段通常都不容易移植。尽管如此,有些情况却要用到这种不可移植的特性。例如,以特定硬件设备所用的形式存储数据。

相关文章:

C语言基础知识:位与位字段

目录 位与字节 位 比特 字节 对齐特性 位字段 位与字节 位 二进制数系统中&#xff0c;每个0或1就是一个位(bit)&#xff0c;位是数据存储的最小单位。其中8 bit就称为一个字节&#xff08;Byte&#xff09;。计算机中的CPU位数指的是CPU一次能处理的最大位数&#xff0…...

新版android studio gradle插件7.4.2.pom一直无法下载问题

android studio同步时候出现org.gradle.api.plugins.UnknownPluginException&#xff0c;Plugin [id: com.android.application, version: 7.4.2] was not found in any of the following sources: pom插件一直无法下载&#xff0c;搞了好几天&#xff0c;简直想砸电脑&#x…...

Shell——变量和引用

1.总结变量的类型及含义&#xff1f; 2.实现课堂案例计算长方形面积&#xff1f;&#xff08;6种方式&#xff09; 3.定义变量urlhttps://blog.csdn.net/weixin_45029822/article/details/103568815 &#xff08;通过多种方法实现&#xff09; 1&#xff09;截取网站访问的协…...

实际开发中一些实用的JS数据处理方法

写在开头 JavaScript 是一种脚本语言&#xff0c;最初是为了网页提供交互式前端功能而设计的&#xff0c;而现在&#xff0c;通过 Node.js&#xff0c;JavaScript 还可以用于编写服务器端代码。 JavaScript 具有动态性、基于原型的面向对象特性、弱类型、多范式、支持闭包执行…...

10:00进去,10:05就出来了,这问的也太变态了···

从外包出来&#xff0c;没想到死在另一家厂子了。 自从加入这家公司&#xff0c;每天都在加班&#xff0c;钱倒是给的不少&#xff0c;所以也就忍了。没想到5月一纸通知&#xff0c;所有人不许加班&#xff0c;薪资直降30%&#xff0c;顿时有吃不起饭的赶脚。 好在有个兄弟内推…...

GPT时代,最令人担心的其实是“塔斯马尼亚效应”

目录 教育到底教什么&#xff1f; 过度依赖GPT可能导致文明退化 GPT可以帮助人类破解“学海无涯极限”悖论 春季学期伊始&#xff0c;全球各地的老师们如临大敌&#xff0c;因为学生们带着ChatGPT杀过来了。Study.com的调研显示&#xff0c;每10个学生中就有超过9个知道Chat…...

基于容器技术和服务发现的全新大数据平台弹性伸缩方法

随着科技的不断发展&#xff0c;各个行业都在不断地数字化和智能化。在这个过程中&#xff0c;大数据技术成为了许多行业的重要支撑。而随着大数据技术的普及&#xff0c;行业分类和设备装置的不断更新换代&#xff0c;弹性伸缩成为了一个不可避免的问题。本文将介绍基于服务发…...

php8 match

刚从 php7 升级到 php8 时 我在使用 switch 语句&#xff0c;结果出现了一个提示&#xff1a; "switch statement can be converted to match expression" 翻译过来就是&#xff1a; switch语句可以转换为match表达式 我当时在想&#xff0c;match 应该是php8 的…...

ADS-B接收机Radarcape

1.设备简介 Radarcape是一款便携、高性能、功能强大的ADS-B地面接收机。Radarcape的设备清单包含&#xff1a;ADS-B接收机主机&#xff0c;专业级ADS-B天线&#xff0c;GPS天线&#xff0c;电源线&#xff0c;网线。 2. 功能特点 Radarcape可以通过网口输出飞机的原始数据D…...

软件测评师2012年下半年考试真题<更新中。。。>

1.2012 年下半年全国计算机技术与软件专业技术资格&#xff08;水平&#xff09;考试日期是 11月4号。 2.在 CPU 中&#xff0c;控制器 不仅要保证指令的正确执行&#xff0c;还要能够处理异常事件。 3.循环冗余校验码&#xff08;CRC) 利用生成多项式进行编码。设数据位为 k 位…...

ChatGPT 使用 拓展资料:开始构建你的优质Prompt

ChatGPT 使用 拓展资料:开始构建你的优质Prompt...

Hystrix原理

一.概述 在软件架构领域&#xff0c;容错特指容忍并防范局部错误&#xff0c;不让这种局部错误不断扩大。我们在识别风险领域&#xff0c;风险可以分为已知风险和未知风险&#xff0c;容错直接应对的就是已知风险&#xff0c;这就要求针对的场景是&#xff1a;系统之间调用延时…...

内网外网分离模式下,通过网关转发,来部署前后端分离的系统

前言 最近为某银行系统部署了一套商城系统&#xff0c;网络环境比较特别&#xff0c;思路记录下&#xff0c;其中商场系统使用前后端分离模式部署。 该银行网络环境&#xff1a; 外网服务器&#xff1a;外网可以访问到它&#xff0c;不能访问外网。 网关服务器&#xff1a;跟…...

基于 Amazon API Gatewy 的跨账号跨网络的私有 API 集成

一、背景介绍 本文主要讨论的问题是在使用 Amazon API Gateway&#xff0c;通过 Private Integration、Private API 来完成私有网络环境下的跨账号或跨网络的 API 集成。API 管理平台会被设计在单独的账号中(亚马逊云科技提供的是多租户的环境)&#xff0c;因为客观上不同业务…...

SSH远程连接时报错kex_exchange_identification: Connection closed by remote host

简介 在SSH服务器上进行远程内容时&#xff0c;会经常出现kex_exchange_identification: Connection closed by remote host内容&#xff0c;主要是由于远程计算机登录节点的数量限制问题。 解释 在 SSH 服务器上&#xff0c;最大并发登录会话数是由 ‘MaxSessions’ 参数来…...

一、CNNs网络架构-基础网络架构

目录 1.LeNet 2.AlexNet 2.1 激活函数&#xff1a;ReLU 2.2 随机失活&#xff1a;Droupout 2.3 数据扩充&#xff1a;Data augmentation 2.4 局部响应归一化&#xff1a;LRN 2.5 多GPU训练 2.6 论文 3.ZFNet 3.1 网络架构 3.2 反卷积 3.3 卷积可视化 3.4 ZFNet改…...

[开发|C++] C++的基本运算符说明笔记

基本运算符说明 C是一种功能强大的编程语言&#xff0c;提供了多种运算符来执行各种基本操作。下面是一些常见的C基本运算符及其说明&#xff1a; 算术运算符&#xff1a; &#xff1a;加法运算符&#xff0c;用于执行两个操作数的相加操作。 -&#xff1a;减法运算符&#xf…...

抖音定位功能的作用

随着智能手机和社交网络的普及&#xff0c;人们日常生活中对于位置信息的需求也越来越高。而抖音作为一款以短视频为主的社交应用&#xff0c;其定位技术也备受关注。本文将就抖音的定位功能进行探究&#xff0c;介绍抖音如何获取、处理和利用用户的位置信息&#xff0c;并探讨…...

阿里 P9 推荐的 Spring 领域巅峰之作,直接颠覆了我对 Spring 的认知

写在前面 你第一次接触 spring 框架是在什么时候&#xff1f;相信很多人和我一样&#xff0c;第一次了解 spring 都不是做项目的时候用到&#xff0c;而是在网上看到或者是听到过一个叫做 spring 的框架&#xff0c;这个框架号称完爆之前的 structs 和 structs2&#xff0c;吸…...

R语言结构方程模型(SEM)在生态学领域中的实践应用

结构方程模型&#xff08;Sructural Equation Model&#xff09;是一种建立、估计和检验研究系统中多变量间因果关系的模型方法&#xff0c;它可以替代多元回归、因子分析、协方差分析等方法&#xff0c;利用图形化模型方式清晰展示研究系统中变量间的因果网络关系&#xff0c;…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器

一.自适应梯度算法Adagrad概述 Adagrad&#xff08;Adaptive Gradient Algorithm&#xff09;是一种自适应学习率的优化算法&#xff0c;由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率&#xff0c;适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...

边缘计算医疗风险自查APP开发方案

核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...

【位运算】消失的两个数字(hard)

消失的两个数字&#xff08;hard&#xff09; 题⽬描述&#xff1a;解法&#xff08;位运算&#xff09;&#xff1a;Java 算法代码&#xff1a;更简便代码 题⽬链接&#xff1a;⾯试题 17.19. 消失的两个数字 题⽬描述&#xff1a; 给定⼀个数组&#xff0c;包含从 1 到 N 所有…...

对WWDC 2025 Keynote 内容的预测

借助我们以往对苹果公司发展路径的深入研究经验&#xff0c;以及大语言模型的分析能力&#xff0c;我们系统梳理了多年来苹果 WWDC 主题演讲的规律。在 WWDC 2025 即将揭幕之际&#xff0c;我们让 ChatGPT 对今年的 Keynote 内容进行了一个初步预测&#xff0c;聊作存档。等到明…...

算法笔记2

1.字符串拼接最好用StringBuilder&#xff0c;不用String 2.创建List<>类型的数组并创建内存 List arr[] new ArrayList[26]; Arrays.setAll(arr, i -> new ArrayList<>()); 3.去掉首尾空格...

Angular微前端架构:Module Federation + ngx-build-plus (Webpack)

以下是一个完整的 Angular 微前端示例&#xff0c;其中使用的是 Module Federation 和 npx-build-plus 实现了主应用&#xff08;Shell&#xff09;与子应用&#xff08;Remote&#xff09;的集成。 &#x1f6e0;️ 项目结构 angular-mf/ ├── shell-app/ # 主应用&…...

python报错No module named ‘tensorflow.keras‘

是由于不同版本的tensorflow下的keras所在的路径不同&#xff0c;结合所安装的tensorflow的目录结构修改from语句即可。 原语句&#xff1a; from tensorflow.keras.layers import Conv1D, MaxPooling1D, LSTM, Dense 修改后&#xff1a; from tensorflow.python.keras.lay…...

高效的后台管理系统——可进行二次开发

随着互联网技术的迅猛发展&#xff0c;企业的数字化管理变得愈加重要。后台管理系统作为数据存储与业务管理的核心&#xff0c;成为了现代企业不可或缺的一部分。今天我们要介绍的是一款名为 若依后台管理框架 的系统&#xff0c;它不仅支持跨平台应用&#xff0c;还能提供丰富…...

【技巧】dify前端源代码修改第一弹-增加tab页

回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码&#xff0c;在知识库增加一个tab页"HELLO WORLD"&#xff0c;完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...

C#最佳实践:为何优先使用as或is而非强制转换

C#最佳实践&#xff1a;为何优先使用as或is而非强制转换 在 C# 的编程世界里&#xff0c;类型转换是我们经常会遇到的操作。就像在现实生活中&#xff0c;我们可能需要把不同形状的物品重新整理归类一样&#xff0c;在代码里&#xff0c;我们也常常需要将一个数据类型转换为另…...