为什么要做字节对齐 alignment?

下面这段 C++ 代码的输出是什么?定义的 Type 占用的字节数(下面简称为字节数)是多少呢?

#include <iostream>struct Type {char a;int b;
};int main(void) {std::cout << sizeof(Type) << '\n';
}

经过编译运行,在 x86-64 Linux 机器上输出的结果是 8。如果将成员变量的字节数相加求和,等于 1 + 4 = 5 字节。那多出来的 3 字节做什么了?

一般,我们会把多出的 3 字节用来做字节对齐。也就引出了文章标题提出的问题:为什么要做字节对齐呢?多占用的字节有什么用处?

首先,程序加载进内存后,需要将指令、数据读取到 CPU 中;CPU 读取数据的速度要远远超过内存的。为了缓解速度差异,引入了 Cache 机制。

而在读写 Cache 中的数据时,一般都是按照一定大小来操作的,这个概念被称为 “Cache line”。在因特尔芯片中,一次操作的大小是 64 个字节。假如现在类型 Type 的对象存储在 Cache 的地址分别为 [60, 61, 62, 63, 64]。如果现在 CPU 去读这个对象,你会发现,它正好分布在两个 Cache line 中(分别是 [0,63] 和 [64, 127]),因此要读两次。

为了尽可能让每次操作都能够访问到完成的数据,而不是分两次进行。编程语言都会引入字节对齐 Alignment 机制(也与 C++ 的处理机制差不多):

  1. 首先,设定每一个基础类型的 alignment 大小,都是 2 的幂。C++ 在 x86-64 Linux 机器上的 alignment 情况如下表(可以通过 alignof(Type) 函数查看):

    类型sizeof(Type)alignof(Type)
    char (unsigned char)11
    short (unsigned short)22
    int (unsigned int)44
    long (unsigned long)88
    float44
    double88
    long double1616
    T*88
  2. 要求某一类型的第一个字节的地址能被 alignment 整除。也就是说,存放 int 值的地址必须是 4 的倍数。

  3. 如果是用户自定义类型,比如文章开头的 struct,它的 alignment 等于 max(所有成员变量的 alignment),也就是 int 类型的 4。

  4. 并且要求 sizeof(Type) 必须是 alignof(Type) 的倍数。

以 Type 为例,它的成员变量占用字节和为 5,不是 4 的倍数,所以要在 a 后面填充 3 个 byte 空闲字节,将 Type 字节数扩充为 8。你会发现 [8n, 8n+1,…, 8n+7] 总是会在一个 Cache line 里。

看到这有的朋友可能会问,这个真的一定会确保对象都在一个 Cache line 里吗?

答案是不能,比如将 Type 改写为下面的形式:

struct Type {char a;int b;int c;
};

首先,通过上面的讲解大家应该都能知道现在 sizeof(Type) == 12,但是 64 不能被 12 整除,也就无法保证对象一定在一次 Cache line 里。

也就是说,字节对齐只是尽可能减少对象需要 Cache line 的统计学次数。

关于不同字节数大小的类型,需要的访问 Cache line 预计次数,可以参考这篇文章。你会发现 9 和 12 字节的预计次数竟然是一样的!

总结

  • 字节对齐的目的是尽可能减少对象需要 Cache line 的统计学次数。
  • 而且,多占用的字节,无法直接访问。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/114505.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

阿里面试(持续更新)

一面&#xff1a; 1 HashMap 实现原理&#xff0c;ConcurrentHashMap 实现原理 HashMap和ConcurrentHashMap都是存储键值对的数据结构&#xff0c;不同的是HashMap是线程不安全的&#xff0c;ConcurrentHashMap是线程安全的&#xff0c;HashMap在高并发情况下会出现数据不一致…

企业知识库软件,快速构建企业知识分享与团队协同的软件

企业知识库是一种特殊的在线协同文档工具&#xff0c;支持包括FAQ、文档、视频、知识图谱等。从本质上讲&#xff0c;它是基于企业知识库软件从而实现内部或外部知识的沉淀、集合、更新、共享等&#xff0c;能为员工或客户提供常见问题的标准回答。 今天我就基于HelpLook &…

敏捷是怎么提高工作效率的

敏捷管理是一门极力减少不必要工作量的艺术。 谷歌、亚马逊、苹果、微信、京东等全球 500 强企业都在用的管理方法&#xff0c;适用于各行各业&#xff0c;被盛赞为应获“管理学的诺贝尔奖”。 它专注于让员工不受种种杂事的羁绊&#xff0c;激发个体斗志&#xff0c;释放出巨大…

阶段六-Day05-MyBatis3

一、多表查询&#xff08;面试题&#xff09; 1. 介绍 多表查询是在企业中必不可少的&#xff0c;无论多么简单的项目里通常会出现多表查询的操作。因为只要是关系型数据库&#xff0c;在设计表时都需要按照范式进行设计&#xff0c;为了减少数据冗余&#xff0c;都会拆成多个…

Proteus仿真--量程自动切换数字电压表(仿真+程序)

本文主要介绍基于51单片机的量程自动切换数字电压表Proteus仿真设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 简介 硬件电路主要分为单片机主控模块、AD转换模块、量程选择模块以及数码管显示模块 &#xff08;1&#xff09;单片机主控模块&#xff1a;单片…

Golang开发软件

1. 引言 Go&#xff08;也称为Golang&#xff09;是一种开源的编程语言&#xff0c;由Google在2007年启动的项目中开发而来。它是一种静态类型的编译型语言&#xff0c;旨在提供高效、可靠的性能。相比于其他编程语言&#xff0c;Golang具有更高的执行效率和并发能力&#xff…

OpenStack云计算平台实战-----创建空白虚拟机

1、创建空白虚拟机 需要注意的步骤会截图一下&#xff0c;其它的基本都是下一步&#xff0c;默认的即可 建议将虚拟机命名为自己的名字加后缀 将处理器数量和每个处理器的内核量都修改为2 将虚拟机的内存设置为8G&#xff0c;不然不够用 将指定磁盘大小设置为200G&#xff0c;…

精讲stable diffusion的controlNet插件

controlNet插件是stable diffusion的一个重要插件&#xff0c;甚至可以说正是因为有了controlNet插件&#xff0c;stable diffusion才会具有midjourney所不具备的独特魅力&#xff01; 我们今天就一起来学习下controlNet插件的安装和每个模型的用法 插件主页 独立的controlN…

微信小程序授权登录介绍

目录 一. 小程序登录如何获取微信用户信息 二. 小程序微信授权登录示例 后台代码 小程序代码 效果展示 三. 微信emoji存储问题 一. 小程序登录如何获取微信用户信息 小程序可以通过微信官方提供的登录能力方便地获取微信提供的用户身份标识&#xff0c;快速建立小程序内…

【Java 进阶篇】手把手教你创建 Bootstrap 旅游网站

随着互联网的普及&#xff0c;旅游行业在全球范围内迅速发展。人们通过网络规划、预订和分享他们的旅行经历。因此&#xff0c;拥有一个令人印象深刻的旅游网站对于吸引游客和提供有用信息至关重要。在本篇博客中&#xff0c;我们将手把手教您如何创建一个令人兴奋的旅游网站&a…

华为eNSP配置专题-OSPF路由协议的配置

文章目录 华为eNSP配置专题-OSPF路由协议的配置0、概要介绍1、前置环境1.1、宿主机1.2、eNSP模拟器 2、基本环境搭建2.1、终端构成和连接2.2、终端的基本配置 3、OSPF路由的配置3.1、OSPF路由的配置3.1.1、在R1上配置OSPF3.1.2、在R2和R3上配置OSPF3.1.3、查看和监控OSPF 华为e…

[传智杯 #5 初赛] I-不散的宴会

洛谷P8877 [传智杯 #5 初赛] I-不散的宴会 题目大意 学生社会可以被看作一个排列成等腰直角三角形的节点阵列。该节点阵列共有 n n n行&#xff0c;第 i i i行共有 i i i个节点&#xff0c;我们将第 i i i行第 j j j列的节点标号为 ( i , j ) (i,j) (i,j)。 这些点具有权值。…

正则表达式之学习笔记

正则表达式学习笔记 一、概念二、正则表达式组成三、常见的正则表达式3.1 .匹配任意字符3.2 * 匹配前一个字符的0个或多个实例3.3 ^ 匹配输入字符串的开头3.4 $ 匹配行尾3.5 [] 匹配字符集合\<\> 精确匹配符号 一、概念 正则表达式是由一系列特殊字符组成的字符串&#…

【笔试题】华为研发工程师编程题

1.汽水瓶 某商店规定&#xff1a;三个空汽水瓶可以换一瓶汽水&#xff0c;允许向老板借空汽水瓶&#xff08;但是必须要归还&#xff09;。 小张手上有n个空汽水瓶&#xff0c;她想知道自己最多可以喝到多少瓶汽水。 数据范围&#xff1a;输入的正整数满足 1≤n≤100 1≤n≤…

localforage-本地存储的优化方案

前言 前端本地化存储算是一个老生常谈的话题了&#xff0c;我们对于 cookies、Web Storage&#xff08;sessionStorage、localStorage&#xff09;的使用已经非常熟悉&#xff0c;在面试与实际操作之中也会经常遇到相关的问题&#xff0c;但这些本地化存储的方式还存在一些缺陷…

让uniGUI支持https

今天在专家的帮助下&#xff0c;成功的让uniGUI支持https了。 首先&#xff0c;去申请个**的证书。我同事去阿里申请的&#xff0c;申请回是一个zip文件&#xff0c;里面有两个文件&#xff0c;一个扩展是per&#xff0c;一个key 然后&#xff0c;把这两个证书文件放到uniGUI…

通过Chain Prompts方式将LLM的能力引入测试平台:正交实验测试用例生成

通过Chain Prompts方式将LLM的能力引入测试平台:正交实验测试用例生成 Chain Prompts Chain Prompts是指在一个对话或文本生成任务中,将前一个提示的输出作为下一个提示的输入,形成一个连续的链条。这种方法常常用于创建连贯的、有上下文关联的文本。在对话系统中,这种方…

微信小程序数据存储方式有哪些

在微信小程序中&#xff0c;数据存储方式有以下几种&#xff1a; 本地存储 本地存储是一种轻量级的数据存储方式&#xff0c;用于存储小量的数据&#xff0c;例如用户的配置信息、页面的状态等。微信小程序提供了 wx.setStorage() 和 wx.getStorage() 方法&#xff0c;用于将数…

【Java基础面试三十六】、遇到过异常吗,如何处理?

文章底部有个人公众号&#xff1a;热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享&#xff1f; 踩过的坑没必要让别人在再踩&#xff0c;自己复盘也能加深记忆。利己利人、所谓双赢。 面试官&#xff1a;遇到过异常吗&#xff0…

reactnative 底部tab页面@react-navigation/bottom-tabs

使用react-navigation/native做的页面导航和tab‘ 官网&#xff1a;https://reactnavigation.org/docs/getting-started 效果图 安装 npm install react-navigation/nativenpm install react-navigation/bottom-tabs封装tabbar.js import { View, StyleSheet, Image } from …