什么是字节对齐?字节对齐与位域的计算

2023-05-16

目录

  • 1.什么是字节对齐?为什么要字节对齐?
  • 2.字节对齐的规则
  • 3.字节对齐的数值
  • 4.位域
  • 5.位域的填充

1.什么是字节对齐?为什么要字节对齐?

字节对齐也称为字节填充, 它是一种牺牲空间换取时间的方法。
字节对齐的作用不仅是便于CPU的快速访问,使CPU的性能达到最佳,而且可以有效地节省存储空间。

例如,32位计算机的数据传输是4字节,64位计算机的数据传输是8字节,这样,struct在默认情况下,编译器会对struct的结构进行(32位机)4的倍数或(64位机)8的倍数的数据对齐。

对于32位机来说,4字节的对齐能够使CPU访问速度提高,如一个long类型的变量,如果跨越了4字节边界存储,那么CPU要读取两次,这样效率就低了。但需要注意的是,如果在32位机中使用1字节或者2字节对齐,不仅不会提高效率,反而会使访问速度降低。

2.字节对齐的规则

  1. 结构体每个成员相对于结构体首地址的偏移量都是成员大小的整数倍。如有不满足,则需要在成员之间加上相应的填充字节。
  2. 结构体的总大小必须为最大对齐数的整数倍,如不满足,则需要在最后一个成员之后加上填充字节。

3.字节对齐的数值

  1. 指定对齐参数值:通过#pragma pack(push, n)设置。
  2. 自身对齐参数值:每个内部类型自身也都有一个对齐参数,一般来说这个对齐参数就是 sizeof(type) 的值,char是1,short是2,int是4,float是4,double是8等。
  3. 有效对齐参数值:内部类型的有效对齐是指它的自身对齐参数和指定对齐参数中较小的那个值;
  4. 结构体整体的有效对齐参数值:是指它的成员中,有效对齐参数最大的那个值。
///< 假设按4字节对齐
#pragma pack(push, 4)
struct data {
  char a;     //a的有效对齐参数值是min(1,4)为1字节,从第1字节开始,占1字节
  char b;      //b的有效对齐参数值是min(1,4)为1字节,从第2字节开始,占1字节
  long long c; //d的有效对齐参数值是min(8,4)为4字节,从第5个字节开始,占8字节
  short d;     //e的有效对齐参数值是min(2,4)为2字节,从第13个字节开始,占2字节
};

它们的和为1字节(a)+1字节(b)+2字节(填充)+8字节(c)+2字节(d)=14字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,最后的总大小为4 * 4 = 16字节。

例题:
采用2字节、4字节、8字节对齐时,sizeof(ABC)的值是多少?

typedef struct tagABC
{
unsigned char ucpa1:2;
unsigned char ucpa2:1;
unsigned char ucpa3:7;
unsigned char ucpa4:6;
unsigned char ucpa5:4;
unsigned char ucpa6:4;
unsigned char ucpa7;
unsigned long ulpa8;
}ABC;

答案是:10、12、12

首先需要知道以下语句的含义

unsigned char ucpa1:2

4.位域

该种形式出现于结构体或共用体的定义中,是位域定义的标准形式。
其使用方式为

struct student
{
	type var_student : n;
};

在结构体student中,成员变量var_student占用空间为n位。(1字节=8位,1 bit = 8 bytes)
n为正整数,其值必须小于type类型占用的位数。比如type如果是int,占4字节32位,那么n必须是1~31之间的整数。

5.位域的填充

  1. 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
  2. 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;
  3. 如果相邻的两个位域字段的类型不同,则各个编译器的具体实现有差异,VC6采取不压缩方式,采用第一节说的字节对齐方式进行。
  4. 整个结构体的总大小采用字节对齐方式的第4点。
  5. 如果位域字段之间穿插着非位域字段,则不进行压缩,采用第一节说的字节对齐方式进行。
  6. 无名的位域不能使用,只能用于填充,位宽为0表示强制下一位域对齐到当前类型的边界。
///< 假设按4字节对齐
#pragma pack(push, 4)
struct data {
    short a : 7;       //从第1个字节开始,占1字节,使用7位
    short b : 5;       //从第2个字节开始,占1字节,使用5位
    long long e : 4;   //与上个类型不一致,e的有效对齐参数值是min(8,4)为4字节,所以从第5个字节开始,占8字节,使用4位
    char f : 5;        //与上个类型不一致,f的有效对齐参数值是min(1,4)为1字节,所以从第13个字节开始,占1字节,使用1位
};

它们的和为1字节(a)+1字节(b)+2字节(填充)+8字节(e)+1字节(f)=13字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,最后的总大小为4 * 4 = 16字节。

///< 假设按4字节对齐
#pragma pack(push, 4)
struct bits8 {
    short a : 3; //从第1个字节开始,占1字节,使用3位
    short : 0;  //占位,占15位,强制下一类型对齐到边界
    char : 3;   //占位,从第3个字节开始,占3位
    char b : 5;  //从第3字节第4位开始,使用5位 
    int i : 4;    //从第5个字节开始,占4字节,使用4位
};

它们的和为2字节(a)+1字节(b)+1字节(填充)+4字节(i)=8字节。
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为4,所以整个结构为4的整数倍,满足条件,最后的总大小为8字节。

最后再来看这道题

typedef struct tagABC
{
unsigned char ucpa1:2;
unsigned char ucpa2:1;
unsigned char ucpa3:7;
unsigned char ucpa4:6;
unsigned char ucpa5:4;
unsigned char ucpa6:4;
unsigned char ucpa7;
unsigned long ulpa8;
}ABC;

a. 2字节对齐时
ucpa1占第一字节的2位,ucpa2占第一字节的1位,由于第一字节只剩下8-2-1=5位,7>5,所以ucpa3要从第二字节开始,同时在第一字节补5位。
同理,ucpa3占用第二字节后只剩下1位,无法容纳ucpa4,所以ucpa4要从第三字节开始,同时在第二字节补1位。
接下来在第三字节补2位,ucpa5从第四字节开始,并可以与ucpa6共用第四个字节。
ucpa7从第五字节开始,占用一个字节。
ulpa8占用4个字节,由于要求二字节对齐,所以ulpa8之前的字节数要为2的整数倍,所以需要补一个字节,使ulpa8从第七字节开始,保证其前面的字节数可以被2整除。
它们的和为1字节(ucpa1、ucpa2)+1字节(ucpa3)+1字节(ucpa4)+1字节(ucpa5、ucpa6)+1字节(ucpa7)+1字节(补)+4字节(ulpa8)=10字节
因为整体结构体还需要进行对齐,结构成员最大有效对齐参数值为2,所以整个结构为2的整数倍,满足条件,最后的总大小为10字节。

字节12345678910
1+2+5(补)7+1(补)6+2(补)4+4888888
成员ucpa1+ucpa2ucpa3ucpa4ucpa5+ucpa6ucpa7ulpa8ulpa8ulpa8ulpa8

b. 4字节对齐时
与2字节对齐相同,仅在ucpa7之后,即第六位字节开始补3位,即比第一种结果多两个字节,为12字节。

c. 8字节对齐时
与4字节对齐相同,为12字节。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

什么是字节对齐?字节对齐与位域的计算 的相关文章

  • apscheduler报错maximum number of running instances

    错误详情 span class token punctuation span WARNING span class token punctuation span span class token punctuation span apsch
  • 复杂KBQA问答方法分类

    复杂KBQA问答方法分类 复杂KBQA问答的主流方法有两类 xff0c 基于语义解析 xff08 SP based xff09 和基于信息检索 xff08 IR based xff09 两类 xff0c 顾名思义 xff0c 基于语义解析的
  • 对比损失的PyTorch实现详解

    对比损失的PyTorch实现详解 本文以SiT代码中对比损失的实现为例作介绍 论文 xff1a https arxiv org abs 2104 03602 代码 xff1a https github com Sara Ahmed SiT
  • ctags 基本使用方法

    ctags 基本使用方法 简介 ctags xff08 Generate tag files for source code xff09 是vim下方便代码阅读的工具 尽管ctags也可以支持其它编辑器 xff0c 但是它正式支持的只有 V
  • Java 生产者和消费者3种实现方式

    使用 Objcet 的 wait 和 notifyAll 实现 使用 BlockingQueue 实现 使用 Lock 的 Condition 的 await signal 实现 使用 Objcet 的 wait 和 notifyAll 实
  • 【python安全攻防】python简易端口扫描器

    文章目录 socket套接字optparse模块socket解析主机进行连接获取bannerthreading多线程端口扫描器python nmap端口扫描 对自己看python绝技的一次学习记录 socket套接字 与TCP端口进行交互
  • EsLint 常用规则

    ESLint 是一个代码规范和错误检查工具 xff0c 有以下几个特性 所有东西都是可以插拔的 你可以调用任意的 rule api 或者 formatter api 去打包或者定义 rule or formatter 任意的 rule 都是
  • qt 手动释放new出堆中的内存,如何释放什么时候释放,qt和c++中使用delete的不同

    http www 360doc com content 20 1019 10 65283686 941181306 shtml
  • C++:error C4996解决方法

    背景 使用fopen sprintf strcpy strstr 等函数 xff0c 在编译c 43 43 程序时报如下错 xff1a error C4996 strncat This function or variable may be
  • call(zoom)_如何解决您的Zoom Call问题

    call zoom A lot of people and businesses have turned to Zoom as their go to video conferencing application However Zoom
  • Nginx配置访问密码(在线|离线安装)

    Nginx配置访问密码 在线 xff5c 离线安装 实现效果 xff1a 1 通过nignx访问的站点或目录 xff0c 需要让用户输入用户名密码才能访问 2 在nginx下 xff0c 提供了ngx http auth basic mod
  • linux下docker安装rabbitmq无法打开控制台

    文章目录 一 安装rabbitmq xff0c 并启动二 访问三 解决问题 linux下使用docker安装rabbitmq后 xff0c 无法访问控制台 xff0c 已解决 一 安装rabbitmq xff0c 并启动 1 拉取镜像 do
  • Wake On Lan(WOL)失败的原因

    Wake On Lan xff0c 失败的原因 发送Magic Packet xff08 魔法数据包 xff09 xff0c 不多阐述 xff0c 如果是编程发包 xff0c 请使用UDP封包 在BIOS中开启 Wake On Lan 选项
  • spring的配置文件

    使用流程 添加spring依赖创建类创建spring配置文件 xff0c 并在配置文件中给要被spring创建和管理的类添加标识 在主程序中加载spring配置文件从容器中获取对象 bean的配置 在spring配置文件中 xff0c 通过
  • 解决vc++运行窗口一闪而过的方法

    1 可以在程序添加头文件 include lt Windows h gt 然后在main函数最后的 return 0 xff1b 前面加上system pause xff1b 2 不要手动按运行键 xff0c 而用快捷键ctrl 43 f5
  • centos 6升级内核小版本、更新yum源和升级gcc版本

    文章目录 前言一 升级内核小版本1 1 设置开机自启动网卡1 2 下载待升级内核小版本的rpm文件1 3 修改内核版本启动顺序 二 更换yum源三 升级g 43 43 版本参考链接 前言 将centos 6 8 2 6 32 642 el6
  • 【PX4_BUG】jMAVSim仿真找不到libawt_xawt.so和libjawt.so文件或jdk版本不匹配的解决方法

    在使用make px4 sitl jmavsim命令进行仿真时出现错误 java lang UnsatisfiedLinkError Can 39 t load library usr lib jvm java 11 openjdk amd
  • Windows Server 2016域控服务器如何取消密码复杂性规则

    图 1 报错截图 具体解决办法 第一步 打开服务器管理 如图直接在 放大镜搜索框里面 直接输入搜索服务器管理或者打开箭头3所示的图标 第二步 点击工具 打开组策略管理 第三步 找到 Default Domain Policy 然后鼠标右击编
  • noVNC搭建

    noVNC搭建 1 环境准备 Os centos7 5准备两台设备 192 168 17 176 和 192 168 17 177 2 安装python环境 安装python3 在192 168 17 176操作如下 查看之前是否存在环境
  • Arduino小项目1---esp8266 WiFi 签到机

    Arduino小项目1 ESP8266 WiFi 签到机 前言0 使用的材料和软件1 准备一个HTML网页A 搭建出适合手机的页面框架B 在body中加入表单元素form标签 xff1a 它的常用属性是action xff0c 就是把表单提

随机推荐

  • 如何找回忘记的Facebook密码

    If you don t use a password manager those complex passwords can be pretty hard to remember If you ve forgotten your Face
  • Cube-SLAM编译遇到的问题

    error iota was not declared in this scope 解决办法 xff1a 报错位置添加 xff1a span class token macro property span class token direc
  • CubeSLAM学习

    Cube SLAM 此代码包含两种模式 xff1a 与ORB SLAM集成的对象SLAM 请参见orb object slam具有ros bag输入的在线SLAM 读取离线检测到的3D对象仅适用于多维数据集SLAM的基本实现 参见objec
  • [转载]PAC模式与全局模式的区别

    区别一 xff1a 使用流量多少不一样 PAC模式 xff1a 节省流量 全局模式 xff1a 流量消耗较多 区别二 xff1a 运行速度快慢不一样 PAC模式 xff1a 国内网站依旧走本地网络 xff0c 速度快 xff0c 绝大部分国
  • 【语音控制ROS】PocketPhinx语音包的使用<三>

    语音控制机器人 语音控制ROS 虚拟机安装Ubuntu14 04 43 ROS indigo xff1c 一 xff1e 语音控制ROS 仿真环境的搭建 xff1c 二 xff1e 用语音来控制机器人移动 前提 xff1a 安装好了ROS环
  • 【C++/文件读写】合并两文件

    要求 编写一程序 xff0c 将两个文件合并成一个文件 代码 span class token macro property span class token directive keyword include span span clas
  • legoloam报错Point cloud is not in dense format, please remove NaN points first!

    错误 Point cloud is not in dense format please remove NaN points first 解决问题 找到utility h将useCloudRIng设置为false 重新编译即可
  • 【转载】C / C++ 读取文件出现乱码解决方法 | 输出到文件出现乱码

    昨天用C语言写了一下文件读取 xff0c 发现读出来的全是乱码 这肯定是文字编码不同导致的 据我查证 xff0c C语言的汉字编码方式是由你电脑决定的 xff0c 所以需要看一下你电脑是什么编码 xff0c 来确定你需要把文本文件改成什么编
  • 【计算机网络】基础概念总结6-子网掩码

    6 子网掩码 6 1 为什么要有子网掩码 随着互联网的飞速发展 xff0c 我们消耗 IP 的速度越来越快 xff0c IP 地址渐渐的又不够用了 xff0c 因此 xff0c 在 1993 年 xff0c 引入了一种新的方法 xff0c
  • 【shell】批量修改文件前缀和后缀

    需求 做实验时需要对相片名称进行修改 xff0c 以递增的顺序 并且修改后缀 奈何网上找的脚本都不能用 xff0c 只有自己写一个 代码 span class token shebang important bin bash span sp
  • 【shell】录制操作

    用途 制作教学用途 使用方法 首先是录制 script t span class token operator span class token file descriptor important 2 span gt span timing
  • Apple Watch上的静音模式,免打扰模式和剧院模式之间的区别(以及何时使用每种模式)

    Since it was introduced the Apple Watch has gained a number of different modes but it s not immediately clear when to us
  • 【C++】STL-unodered_map

    文章目录 STL unodered map简介unordered map与map对比自定义key测试参考 STL unodered map 简介 unordered map 容器 xff0c 直译过来就是 34 无序 map 容器 34 的
  • Shell函数参数

    在shell中调用函数时 xff0c 可以向其传递参数 xff0c 其中常用的特殊变量如下表所示 xff1a 函数参数 含义 传递到脚本或函数的参数个数 n 1表示第一个参数 xff0c 2表示第二个参数 注意 xff0c 当n gt 61
  • Dockerfile

    Dockerfile Dockerfile是一种文本文件 xff0c 用于定义如何构建Docker镜像 它包含一系列的指令 xff0c 告诉Docker引擎如何在容器中构建和运行应用程序 Dockerfile指令分类 xff1a 基础镜像指
  • thonny中文版|python编辑

    由于人工智能的兴起 xff0c python语言成了最受欢迎的编程语言 xff0c 为此小编给广大新手用户带来了thonny编辑器 xff0c 这是一款相当优秀的python初学者专用编程学习工具 该软件基于python内置图形库tkint
  • 如何限制HTML中select标签option可见选项数目

    如何限制HTML中select标签option可见选项数目 在使用select标签的时候 xff0c 如果option选项太多 xff0c 会造成下拉列表变得很长 xff08 浏览器默认20条 xff09 如果想控制select中的opti
  • 如何解决win7休眠后自动唤醒的现象

    http jingyan baidu com article ca00d56c50e598e99eebcfea html
  • java实现x 的平方根

    class Solution public int mySqrt int x int left 61 1 int right 61 x int mid while left lt 61 right mid 61 left 43 right
  • 什么是字节对齐?字节对齐与位域的计算

    目录 1 什么是字节对齐 xff1f 为什么要字节对齐 xff1f 2 字节对齐的规则3 字节对齐的数值4 位域5 位域的填充 1 什么是字节对齐 xff1f 为什么要字节对齐 xff1f 字节对齐也称为字节填充 xff0c 它是一种牺牲空