深入理解字节对齐

2023-11-11

基础知识了解

一、操作系统位数、CPU位数、指令集

1.操作系统–32-bit(x86)和64-bit(x64)

(1)位数

  每个时钟周期内,处理器处理二进制代码数,即“0”和“1”的个数。

(2)64-bit

  优点:①可以进行更大范围的整数运算;②可以支持更大的内存。

2.处理器CPU位数

  CPU位数=CPU中寄存器的位数=CPU能够一次并行处理的数据宽度(位数)=数据总线宽度;
  //现在的计算机处理器一般都是64位,这是硬件的事。

3.CPU指令集

  CPU为了实现其功能设计了指令集,即是CPU的全部指令,这是机器语言。计算机的所有功能都是基于CPU的指令集。指令集和CPU的位数是有联系的。

  指令集的作用, 就是告诉程序员/编译器, 汇编一定要有格式. 支持什么指令, 指令带什么限制条件, 用什么操作数, 用什么地址, 都是指令集规范的内容, 要是写错了, 就无法翻译成机器码.

  指令集规范汇编, 汇编可以翻译成机器码, 机器码告诉CPU每个周期去做什么. 因此, CPU指令集是描述CPU能实现什么功能的一个集合, 就是描述"CPU能使用哪些机器码"的集合"。X86是指令集的代号。
  那么指令集在CPU里就代表: 只有CPU指令集范围内的指令可以被成功的译码, 并送往CPU流水线后端去执行.

4.寄存器

  寄存器是CPU内部用来创建和储存CPU运算结果和其它运算结果的地方。

5.关系

  操作系统位数 = 其所依赖的指令集位数 <= CPU位数。

6.计算机字长(机器字长)

  计算机字长(机器字长)取决于数据总线的宽度,通常就是CPU一次能处理的数据的位数(CPU位数)。

7.总结

  在标准c++中,int的定义长度要依靠你的机器的字长,也就是说,如果你的机器是32位的,int的长度为32位,如果你的机器是64位的,那么int的标准长度就是64位,比如16位机上,sizeof(int) = 2,而32位机上sizeof(int) = 4;32位机上sizeof(long) = 4,而64位机上sizeof(long) = 8。

  但是在32位机器和64机器中int类型都占用4个字节,因为一般编译器可以根据自身硬件来选择合适的大小,但是需要满足约束:short和int型至少为16位,long型至少为32位,并且short型长度不能超过int型,而int型不能超过long型

  这即是说各个类型的变量长度是由编译器来决定的,而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节(例如,GCC)。

理解字节对齐

二、字节对齐

1.什么是字节对齐?

  现代计算机中,内存空间按照字节划分,理论上可以从任何起始地址访问任意类型的变量。但实际中在访问特定类型变量时经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序一个接一个地存放,这就是对齐。

  变量存的起始地址必须具备某些特性----“对齐”,比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除。


  对齐跟数据在内存中的位置有关。为了使得CPU能快速对变量进行访问,变量存的起始地址必须具备某些特性,即“对齐”,比如4字节的int型,其起始地址应该位于4字节的边界上,即起始地址能够被4整除。====>>>>cpu类型,编译器类型。

2.为什么要字节对齐

①首先,不同硬件平台对存储空间的处理上存在不同;

  某些平台对特定类型的数据只能从特定地址开始存取,而不允许其在内存中任意存放。例如,Motorola 68000 处理器不允许16位的字存放在奇地址,否则会触发异常,因此在这种架构下编程必须保证字节对齐。

②根本原因在于CPU访问数据的效率问题;

  以32位机为例,它每次取32个位,也就是4个字节。以int型数据为例,如果它在内存中存放的位置按4字节对齐,也就是说1个int的数据全部落在计算机一次取数的区间内,那么只需要取一次就可以了。如图2-1。如果不对齐,很不巧,这个int数据刚好跨越了取数的边界,这样就需要取两次才能把这个int的数据全部取到,如图2-2,这样效率也就降低了。
在这里插入图片描述

③其次节约空间。

  应该辩证地看:合理对齐,则节约空间;否则浪费空间。如下例:
在这里插入图片描述
  结构体TEST1中包含一个4字节的int数据,一个1字节char数据和一个2字节short数据;TEST2也一样。按理说TEST1和TEST2的大小应该都是7字节。之所以出现上述结果,就是因为编译器要对数据成员在空间上进行对齐。

3.如何对齐

3.1 标准类型(基本数据类型):

  基本类型包括char、int、float、double、short、long等基本数据类型。
  对齐要求:起始地址为其长度的整数倍即可。如,int类型的变量起始地址要求为4的整数倍。
思考:int究竟占多少个字节?
  **操作系统:**每个时钟周期内,处理器处理二进制代码数,即“0”和“1”的个数。如64-bit,32-bit
  **CPU位数:**CPU中寄存器的位数=CPU能够一次并行处理的数据宽度(位数)=数据总线宽度;64-bit,32-bit。
  **关系:**操作系统位数 = 其所依赖的指令集位数 <= CPU位数。

int的定义长度要依靠机器的字长,由编译器结合自身硬件选择。

约束条件: short和int型至少为16位,long型至少为32位,并且short型长度不能超过int型,而int型不能超过long型。这即是说各个类型的变量长度是由编译器来决定的,而当前主流的编译器中一般是32位机器和64位机器中int型都是4个字节。

  理论上,int代表机器自然长度,即CPU位数,在32位CPU,应该占4字节,64位CPU,应该占8字节。
  实际上,由编译器和CPU共同决定,主流的编译器编译程序将int解释为4字节。
在这里插入图片描述

3.2 数组:

  按照基本数据类型对齐,第一个对齐了后面的自然也就对齐了。

3.3 结构体

  成员可以为:基本类型,复合类型(基本类型、数组、结构、联合、函数指针)
  结构体中每个数据类型都要对齐,对齐值位其成员中自身对齐值最大的那个值。
在这里插入图片描述在这里插入图片描述

3.4 联合体

  联合体的内存除了取最大成员内存外,还要保证是所有成员类型size的最小公倍数。
在这里插入图片描述
  
   当然只取最大的int数组的大小12没错,但是double是8字节的,而此时联合体已经按int的4字节对齐了,所以还要额外多加4字节的内存来保证8的倍数。所以最后结果是16。

  所以联合体的内存除了取最大成员内存外,还要保证是所有成员类型size的最小公倍数

3.5 指定对齐方式

   #pragma pack(n)   //设置n字节对齐
  #pragma pack()   //取消自定义字节对齐方式

  以n和结构体中最长的成员的长度中较小者为其值。

  __attribute((aligned (n))) //设置n字节对齐
  attribute ((packed))   //设置1字节对齐
  (gcc特性)

  让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。
在这里插入图片描述
  微软的  __alignof( type )
  如:
    typedef __declspec(align(32)) struct { int a; } S;
    _alignof(S) 等于 32

总结:
  ①基本类型:自身对齐
  ②数组:
  ③联合:成员最大对齐值,公倍数;
  ④结构体:其成员中自身对齐值最大的那个值。
  ⑤指定对齐方式:
    #pragma pack (n)和pragma pack ();
    attribute((aligned(n)))和__attribute__((packed))。
  ⑥数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小者,即有效对齐值=min{自身对齐值,当前指定的pack值};注意_attribute__。

4.字节序和网络序

4.1 字节序

(1) what–
  概念:字节的高低位存放顺序。
  单字节与多字节:
    单字节:按bit存储,通常处理方式相同;
    多字节:多个字节存储有顺序之分。
在这里插入图片描述
(2) how–
  大字节序(Big-Endian,大端序):最高有效字节在最前面的方式,即数据的低字节保存在内存的高地址中,而数据的高字节保存在内存的低地址中。(左图)
  小字节序(Little-Endian,小端序):最低有效字节在最前面的方式,数据的低字节保存在内存的低地址中,而数据的高字节保存在内存的高地址中。(右图)
在这里插入图片描述
(3) why–
  编写网络程序时,主机之间通过网络相互通信,不同主机之间可能采用不同的方法,而且网络字节序和主机字节序也可能不同。
在这里插入图片描述在这里插入图片描述

4.2 网络序

  网络传输一般采用大字节序,也称为网络字节序或网络序。IP协议中定义大字节序为网络字节序。

  对于可移植的代码来说,将接收的网络数据转换成主机的字节序是必须的,一般会有成对的函数用于把网络数据转换成相应的主机字节序或反之。

转换函数:
  Htonl、htons用于主机序转换到网络序;
  ntohl、ntohs用于网络序转换到本机序。
  
注意:
  对于单字符或小于单字符的几个bit数据,是不必转换的,因为在机器存储和网络发送的一个字符内的bit位存储顺序是一致的。

5.字节对齐的隐患

  空间换时间。

6.字节对齐应用

  本地
  网络传输

代码验证:
  环境:
  操作系统:x86_64-redhat-linux;编译器:gcc
  操作系统:win7-64位;编译器:vc

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

深入理解字节对齐 的相关文章

  • 锁定 ASP.NET 应用程序变量

    我在 ASP NET 应用程序中使用第三方 Web 服务 对第 3 方 Web 服务的调用必须同步 但 ASP NET 显然是多线程的 并且可能会发出多个页面请求 从而导致对第 3 方 Web 服务的同时调用 对 Web 服务的调用封装在自
  • C free() 是如何工作的? [复制]

    这个问题在这里已经有答案了 可能的重复 malloc 和 free 如何工作 https stackoverflow com questions 1119134 how malloc and free work include
  • XPATH 查询、HtmlAgilityPack 和提取文本

    我一直在尝试从名为 tim new 的类中提取链接 我也得到了解决方案 给出了解决方案 片段和必要的信息here https stackoverflow com questions 2982862 extracting a table ro
  • 将设置函数(setter)标记为 constexpr 的目的是什么? [复制]

    这个问题在这里已经有答案了 我无法理解将 setter 函数标记为的目的constexpr 自 C 14 起这是允许的 我的误解来自以下情况 我使用 constexpr c tor 声明一个类 并且我将通过创建该类的 constexpr 实
  • 带有运算符语法的错误消息,但不带有函数语法的错误消息

    为什么我在调用 unary 时收到错误消息 使用运算符语法 如果我用函数语法调用它就可以了 现场演示 https godbolt org z j7AbeQ template
  • while循环中的变量初始化

    我有一个可以分块读取文件的函数 public static DataObject ReadNextFile 数据对象看起来像这样 public DataObject public string Category get set And ot
  • 为什么需要数字后缀?

    C 语言 我确信还有其他语言 需要在数字文字末尾添加后缀 这些后缀指示文字的类型 例如 5m是一个小数 5f是一个浮点数 我的问题是 这些后缀真的有必要吗 或者是否可以从上下文中推断出文字的类型 例如 代码decimal d 5 0应该推断
  • 如何在win32中使用GetSaveFileName保存文件?

    我编写此代码是为了获取 fileName 来保存我的文件 include stdafx h include
  • 如何使用递归查找数字中的最小元素 [C]

    好的 所以我正在准备我的 C 考试 当谈到递归时我有点卡住了我是大学一年级的学生 这对我来说似乎有点困难 练习要求在给定的数字中使用递归函数我需要找到最小的元素 例如 52873 是 2 程序需要打印 2 include
  • 使用 OleDbCommandBuilder 时访问 SQL 语法错误

    我要在 C 中使用 OleDbDataAdapter 在 Access 数据库中插入数据 但收到错误消息INSERT INTO 命令中的语法错误 BackgroundWorker worker new BackgroundWorker Ol
  • doxygen c++:记录由“using”声明公开的私有继承成员

    作为一个例子 我有以下课程 class A public void methodOne class B private A public Brief description using A methodOne 我还没有找到强制 doxyge
  • C# 中的 C/C++ 代码编译器

    在 C 中 我可以使用下面的代码编译 VB 和 C 代码 但无法编译 C C 代码 有什么办法可以做到这一点吗 C 编译器 public void Compile string ToCompile string Result null st
  • C 中使用 getrandom 实现随机浮点数

    我试图生成一个介于 0 和 1 之间的随机浮点数 无论是在 0 1 还是 0 1 对我来说都不重要 网上关于此的每个问题似乎都涉及rand 呼叫 播种time NULL 但我希望能够每秒多次调用我的程序 并每次都获得不同的随机数 这引导我找
  • 浮点字节序?

    我正在为实时海上模拟器编写客户端和服务器 并且由于我必须通过套接字发送大量数据 因此我使用二进制数据来最大化可以发送的数据量 我已经了解整数字节顺序以及如何使用htonl and ntohl为了规避字节顺序问题 但我的应用程序与几乎所有模拟
  • Linq.Select() 中的嵌套表达式方法调用

    I use Select i gt new T 每次手动点击数据库后将我的实体对象转换为 DTO 对象 以下是一些示例实体和 DTOS 用户实体 public partial class User public int Id get set
  • Xamarin.Forms UWP 项目中标题栏和选项卡之间令人恼火的空白

    我几乎是新手Xamarin Forms我正在开发一个相当简单的跨平台应用程序 该应用程序在 Android 中显示得足够好 但在 UWP 中却出现了一个愚蠢的空白 该项目由一个 TabbedPage 组成 其中包含 4 个 Navigati
  • 这种尺寸对齐是如何工作的

    对于所提供的评论 我无法理解以下代码 这段代码的作用是什么 以及等效的代码是什么8 aligned segment size must be 4 aligned attr gt options ssize 3 Here ssize is o
  • 将 char 绑定到枚举类型

    我有一段与此非常相似的代码 class someclass public enum Section START MID END vector section Full void ex for int i 0 i section
  • 如何在c linux中收听特定接口上的广播?

    我目前可以通过执行以下操作来收听我编写的简单广播服务器 仅广播 hello int fd socket PF INET SOCK DGRAM 0 struct sockaddr in addr memset addr 0 sizeof ad
  • 使用 C# 动态创建按钮并按预定义的顺序放置它们

    NET 4 5 C 创建 Windows 窗体 我想动态创建和添加按钮并为其分配单击事件 但希望它们以特定的方式动态放置 就像图像一样 我的问题是如何以上述方式动态放置按钮 即 4x4 格式 一行 4 个按钮 4 列 但行数不受限制 是否可

随机推荐

  • NLP中的数据增强方法!

    作者简介 大家好我是 uu 人工智能硕博在读 精通python 某大厂nlp算法经历 机器学习 深度学习 自然语言处理 计算机视觉 个人主页 uu主页 觉得uu写的不错的话 麻烦动动小手 点赞 收藏 评论 今天给大家带来的刷题系列是 NLP
  • BUS creator & selector、Mux&Demux

    2 3 总线BUS creator selector Bus Creator 由几路输入信号合成为一条总线信号 Bus Selector 由总线信号中选取需要的一路或几路信号输出 Mux 信号合成 Demux 信号分解 区别 Bus的可选择
  • vue web在线聊天功能实现

    上一篇介绍了vue怎么实现无限滚动窗体 这一篇就具体怎么使用vue实现web在线聊天功能展开深入讨论 对尚且不清楚怎么实现无限滚动窗体的 可前往这里查看 vue和iview实现无限滚动的正确解法 先看看最终实现的效果 实现过程 无限滚动窗体
  • 【ChatGPT进阶】如何使用ChatGPT做知乎好物?

    如果你想通过知乎赚钱 知乎好物是一个不错的选择 门槛很低 而且是一个可以长期 躺赚 的项目 如果你会ChatGPT的话 可以去卷同行 知乎好物是什么 知乎好物是一种在知乎平台上创作内容或回答问题时 使用 好物推荐 功能在内容中插入商品卡片
  • AI绘画StableDiffusion美女实操教程:斗破苍穹-小医仙-天毒女(附高清图下载)

    小医仙 是天蚕土豆所著玄幻小说 斗破苍穹 1 及其衍生作品中的角色 身负厄难毒体 食毒修炼 万毒不侵 通体毒气 这种会无意识地杀死别人的体质让天性善良的小医仙成为人憎鬼厌的天毒女 在萧炎多次帮助下得以控制 出图效果展示 资源整合 今天我们就
  • springboot集成RabbitMQ-超级详细步骤

    本文对应的代码地址 https github com zhangshilin9527 rabbitmq study 前置工作 1 安装rabbitmq 2 登录 地址 http localhost 15672 账号密码 guest gues
  • mybatis学习(31):修改部分字段(有外键,先查询,再修改)

    目录结构 com geyao mybatis mapper BlogMapper类 package com geyao mybatis mapper import java util List import java util Map im
  • vue利用路由控制实现登录功能

    未使用服务器接口 登录信息保存在cookie中 可以实现登录功能 vue交流群203849104 vue使用cookie首先需要安装cookie npm install js cookie 然后在router下面的index js文件中引入
  • 线程池ThreadPoolExecutor源码解析

    参考视频 首先回顾一下创建线程等的三种方式 第一个是直接继承Thread类 重写run方法 这个其实内部也是继承了Runnable接口重写run方法 比如 public class MyThread extends Thread Overr
  • oracle查看数据文件大小,路径及修改大小

    查看数据文件占用大小使用大小 select b file id 文件ID号 b tablespace name 表空间名 b bytes 1024 1024 M 字节数 b bytes sum nvl a bytes 0 1024 1024
  • json11库的使用

    JSON JavaScript Object Notation 是一种轻量级的文本数据交换格式 易于让人阅读 同时也易于机器解析和生成 尽管JSON是Javascript的一个子集 但JSON是独立于语言的文本格式 并且采用了类似于C语言家
  • echarts图表的label太长解决办法

    如图 这个echarts图标的y轴label文字因为太长显示不全 这时我们可以选择使用formatter换行显示 具体代码如下 yAxis type category data 火灾 洪涝 急救 消防 公安 axisLabel format
  • Angular 下的 function

    angular lowercas 将指定的字符串转换为小写的 Usage 使用方法 angular lowercase string Arguments Param Type Details string string 字符串转换成小写 R
  • c语言二叉树链式存储,二叉树链式存储基本操作(C语言)

    1 二叉链的定义 LinkBinTree h文件 二叉树结点结构 typedef struct binnode int data struct binnode lchild struct binnode rchild BinNode 二叉树
  • Host is not allowed to connect to this MySQL server解决方法

    这个错误 其实就是我们安装的MySQL不允许远程登录 解决方法如下 1 在装有MySQL的机器上登录MySQL mysql u root p密码 执行use mysql select host from user where user ro
  • mongodb的MapReduce幂等性

    习惯用MapReduce来做mongodb的聚合 这一次遇到一点小问题 原数据如下 使用一个简单的MapReduce来验证一下数据 map function emit clientKey this clientKey dtime this
  • IDEA中SpringBoot启动错误无法加载主类

    1 项目里面 idea文件 删除 重启idea mvn claean install
  • MiniGUI 自定义控件教程7

    接着上次的教程继续 这次给大家介绍的是界面美观的进度条控件 它功能上和MiniGUI原有的进度条控件 CTRL PROGRESSBAR 是一样的 其实进度条也就是那些功能 哪还能整出别点什么花样哦 一 功能确定 1 要具有MiniGUI原有
  • ORACLE等待事件类型【Classes of Wait Events】

    每一个等待事件都属于某一类 下面给出了每一类等待事件的描述 Every wait event belongs to a class of wait event The following list describes each of the
  • 深入理解字节对齐

    C语言 字节对齐 基础知识了解 一 操作系统位数 CPU位数 指令集 1 操作系统 32 bit x86 和64 bit x64 1 位数 2 64 bit 2 处理器CPU位数 3 CPU指令集 4 寄存器 5 关系 6 计算机字长 机器