一文了解什么是字节对齐(超详细)

2023-11-06

1.什么是字节对齐

得分点 什么是内存对齐、内存对齐的原因、内存对齐的规则
标准回答

  1. 什么是内存对齐

现代计算机中内存空间都是按照 字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会要求这些数据的首地址的值是某个数 k(通常它为4或8)的倍数,这就是所谓的内存对齐。

  1. 内存对齐的原因
  • 平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的。某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。
  • 性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问,而对齐的内存访问仅需要一次访问。
  1. 内存对齐的规则
  • 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。可以通过预编译命令 #pragma pack(n),n = 1,2,4,8,16 来改变这一系数。
  • 有效对其值:是给定值 #pragma pack(n) 和结构体中最长数据类型长度中较小的那个,有效对齐值也叫对齐单位。
  • 结构体第一个成员的偏移量(offset)为0,以后每个成员相对于结构体首地址的 offset 都是该成员大小与有效对齐值中较小那个的整数倍,如有需要编译器会在成员之间加上填充字节。
  • 结构体的总大小为有效对齐值的整数倍,如有需要编译器会在最末一个成员之后加上填充字节。

2.空类

class A
{}

对空类做sizeof()计算时应当等于1

3.带虚函数的类

如果有一个类,包含两个32位整型的数据成员,一个普通成员函数,还有一个virtual虚函数,在32位机器上,这个类sizeof()计算的时候得到多少,编译是4字节对齐

32位机器

#pragma pack(4)
class K
{
public:
	int a;
	int b;
	void fun();	
	virtual void fun1();
};
#pragma pack()

a占4个字节
b占4个字节
void fun不占用内存
因为有一个virtual虚寒函数,有一个虚函数指针,32系统中占用4个字节

所以,占用12个字节。

  • 如果变成8字节对齐呢,应该是多大?
#pragma pack(8)
class K
{
public:
	int a;
	int b;
	void fun();	
	virtual void fun1();
};
#pragma pack()

也许你会觉得是16,但是正确的结果是12.

为什么依然还是12呢?

因为字节对齐的规则规定,
对于结构体,他的有效对齐值,是#pragma pack()和该结构体中最大数据成员两者中的较小的那个值。
这里#pragma pack(8)值为8,但K class中最大数据成员为4个字节,所类K依然按照4字节对齐。

  • 如果一个成员函数变成2个成员函数呢?
#pragma pack(8)
class K
{
public:
	int a;
	int b;
	void fun();	
	void fun2();
	virtual void fun1();
};
#pragma pack()

sizeof(K)依然是占用12个字节。
因为成员函数不占用类对象的内存的。

  • 如果增加一个虚函数,变成两个虚函数了呢?
#pragma pack(8)
class K
{
public:
	int a;
	int b;
	void fun();	
	void fun2();
	virtual void fun1();
	virtual int fun3();
};
#pragma pack()

sizeof(K)依然是占用12个字节。
因为每个类只维护一个虚函数指针,所有的虚函数都放在虚函数表中呢。
32位系统中,指针占用4个内存。

  • 再增加一个char类型,大小会变成多少?
#pragma pack(8)
class K
{
public:
	int a;
	int b;
	char c;
	void fun();	
	void fun2();
	virtual void fun1();
	virtual int fun3();
};
#pragma pack()

答案是:16字节
虽然,#pragma pack为8,但K类最大数据成员大小占4个字节,
所以K类按照4字节对齐。
a占4个字节0-3
b占4个字节4-7
c占一个字节,8-11
虚函数表指针,必须从4的倍数开头,12-15

64位机器

#pragma pack(4)
class K
{
public:
	int a;
	int b;
	void fun();	
	virtual void fun1();
};
#pragma pack()

答案是:16字节
因为64位机器下,虚函数表指针为8个字节

  • 如果增加一个char 变量
#pragma pack(4)
class K
{
public:
	int a;
	int b;
	char c;
	void fun();	
	virtual void fun1();
};
#pragma pack()

答案是:20个字节,因为有效对齐值为4,

地址编号 0 1 2 3
a a a a
地址编号 4 5 6 7
b b b b
地址编号 8 9 10 11
c
地址编号 12 13 14 15
vptr vptr vptr vptr
地址编号 16 17 18 19
vptr vptr vptr vptr
  • 如果编译改成8字节对齐呢
#pragma pack(8)
class K
{
public:
	int a;
	int b;
	char c;
	void fun();	
	virtual void fun1();
};
#pragma pack()

答案是:24个字节
因为8字节对齐,vptr需要从8的倍数开始存储。

地址编号 0 1 2 3
a a a a
地址编号 4 5 6 7
b b b b
地址编号 8 9 10 11
c
地址编号 12 13 14 15
地址编号 16 17 18 19
vptr vptr vptr vptr
地址编号 20 21 22 23
vptr vptr vptr vptr
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

一文了解什么是字节对齐(超详细) 的相关文章

  • 在 JavaScript 中引用 C# 变量

    我已经阅读了很多线程 但我不明白为什么这不起作用 我正在创建一个将用作导航栏的 SharePoint Web 部件 一切都很顺利 直到我尝试在 JS 代码中引用 C 变量 这是来自 VisualWebPart1UserControl asc
  • Xamarin 测试记录器选项有错误。无法记录自动化测试

    选项 gt Xamarin gt Xamarin Test Recorder 中的所有设置都有错误 我的桌面上安装了 Visual Studio 2015 企业版 以及 Xamarin 和 Xamarin Test Recorder 插件
  • 从 unsigned char* 到 char* 的转换无效

    这是一个代码 1 int main int argc char argv 2 3 signed char S psc 4 unsigned char U pusc 5 char C pc 6 7 C S 8 C U 9 10 pc psc
  • ASP.NET 如何在 Web API 中读取多部分表单数据?

    我将多部分表单数据发送到我的 Web API 如下所示 string example my string HttpContent stringContent new StringContent example HttpContent fil
  • 基于多线程的 RabbitMQ 消费者

    我们有一个 Windows 服务 它监听单个 RabbitMQ 队列并处理消息 我们希望扩展相同的 Windows 服务 以便它可以监听 RabbitMQ 的多个队列并处理消息 不确定使用多线程是否可以实现这一点 因为每个线程都必须侦听 阻
  • ptrace和waitpid有什么关系?

    我正在练习使用ptrace但我不太了解它和之间的关系waitpid 这是我的测试程序 int main int argc char argv pid t pid 22092 if ptrace PTRACE ATTACH pid NULL
  • 如何准备sql语句并绑定参数?

    不幸的是 文档 http www sqlite org完全缺乏示例 这真的很奇怪 就好像它假设所有读者都是优秀的程序员一样 然而 我对C 并且无法真正从文档中弄清楚如何真正准备和执行语句 我喜欢它的实施方式PDO for PHP 通常 我只
  • C# 中输入按键

    我尝试了这段代码 private void textBox1 KeyPress object sender KeyPressEventArgs e if Convert ToInt32 e KeyChar 13 MessageBox Sho
  • 如何将 mat 转换为 array2d

    我为dlib http dlib net face landmark detection ex cpp html那里的面部地标代码使用 array2d 来获取图像 但我喜欢使用 Mat 读取图像并转换为 array2d 因为 dlib 仅支
  • 如何在控制器中使用多个 DBContext

    如何在控制器中使用多个 DBContext 我尝试以不同的方式重载构造函数 一些控制器 public C1 DBContext1 a DBContext2 b DBContext3 c public C1 DBContext1 a publ
  • 是否可以在对Where 的调用中调用命名方法?

    我试图从 RedGate 的这本免费电子书中了解 Linq 的一些性能影响ftp support red gate com ebooks under the hood of net memory management part1 pdf f
  • 使用 ClosedXML 附加到 excel 文件

    我需要将新数据附加到使用 ClosedXML 创建的现有 Excel 文件中 如何使用 ClosedXML 附加到 Excel 文件 如何获取最后一条记录的行号并将其附加到该行号上 或者还有其他内容 Thanks 打开现有工作簿 然后使用L
  • VS C# 中的依赖地狱,找不到依赖项

    我创建了一个图表 C 库 我们称之为chartlibrary 它本身依赖于多个第三方 dll 文件 在另一个可执行项目中 我们称之为chartuser 我参考了chartlibrary项目 两个项目位于 Visual Studio 中的同一
  • 为什么 std::atomic 比 volatile bool 慢很多?

    多年来我一直使用 volatile bool 来控制线程执行 并且效果很好 in my class declaration volatile bool stop In the thread function while stop do th
  • C# 中的类和模块有什么用

    有人可以解释一下类和模块之间的区别吗 你什么时候使用其中一种而不是另一种 我正在使用 C 更新 我的意思是相当于 VB 模块的 C 版本 这在很大程度上取决于您所指的 模块 Visual Basic 的模块 C 中没有真正等效的 VB Ne
  • C# 从今天起 30 天

    我需要我的应用程序从今天起 30 天后过期 我会将当前日期存储在应用程序配置中 如何检查应用程序是否已过期 我不介意用户是否将时钟调回来并且应用程序可以正常工作 用户太愚蠢而不会这样做 if appmode Trial string dat
  • 如何使用 MongoDB 实现 ASP.NET Core 3.1 Identity?

    是一个 API 用于简化后端和逻辑代码来管理用户 密码 个人资料数据 角色 声明 令牌 电子邮件确认等 对于 Visual Studio 来说 支撑脚手架 https learn microsoft com en us aspnet cor
  • SQL Server CE 不兼容的数据库版本

    我有一个 SQL Server CE 4 0 数据库 sdf文件 当我尝试从我的应用程序 WPF 对数据库进行查询时 出现以下错误 数据库版本不兼容 如果这是兼容文件 请运行修复 其他情况请参考文档 数据库版本 4000000 请求的版本
  • Cordova 上的 ClearCookiesAsync()

    我正在尝试使用 wp8 cordova 中的插件来清除 WebBrowser cookie 我已经让它与 JavaScript 进行通信 并且我的 c 文件中有类似这样的内容 using WPCordovaClassLib Cordova
  • 从 git 签出后 nuget dll 丢失

    I have a C solution containing different projects On those projects I have some normal nuget packages like Newtonsoft Js

随机推荐

  • axure能做剪切蒙版吗_Axure图片裁切功能

    平时做原型时经常会用到一张图片的某些部分 这时候我们一般都会借助于其他图片处理工具先处理好 再导入到原型中 其实Axure有简单的图片裁切功能 基本可以满足我们大部分的需求 下面介绍一下 使用axure7 1 图片裁割 通过该功能可以把图片
  • C++ 中 enable_shared_from_this 的使用总结

    背景 enable shared from this 是 C 11 定义在头文件 include 中的一个模板类 其作用是在类的内部安全的得到 this 指针的 shared ptr 版本 获取 this 的 shared ptr 版本 概
  • 文件的blob、base64、File的转化

    前言 blob base64 File的互转 base64 File function toFile ndata ndata为base64格式地址 let arr ndata split mime arr 0 match 1 bstr at
  • DALL-E-2 论文水记

    DALL E 2 论文水记 模型示意图 虚线上面是 CLIP 的训练流程 虚线下面是文字生成图像的流程 我们有一个 prior 模型和一个 decode 模型 先把 text embeding 输入 prior 模型 得到 image em
  • How to run Android apps in tablet mode on your phone

    转自 http www littlegreenrobot co uk tutorials how to run android apps in tablet mode on your phone How to run Android app
  • 2.6内核的通用的编译步骤

    2 6内核的通用的编译步骤 1 下载源码并解压 虽然我们可以将内核源码存放在任何自己找得到的地方 但通常还是会将内核源码下载到 usr src目录并解压 cd usr src wget ftp kernel org pub linux ke
  • Android——AVD无法启动解决方法

    起因 最近安装了Android Studio开始瞎捣鼓 安装的时候配置的是自带的Android Virtual Device AVD 然后想在虚拟机上跑以下demo 发现虚拟机怎么都启动不了 起初我以为是系统找不到我的虚拟机的位置导致 因为
  • C# 说说lock

    一 MSDN的定义 lock 语句获取给定对象的互斥 lock 执行语句块 然后释放 lock 持有 lock 时 持有 lock 的线程可以再次获取并释放 lock 阻止任何其他线程获取 lock 并等待释放 lock lock 关键字可
  • 基于TF-IDF+Tensorflow+PyQt+孪生神经网络的智能聊天机器人(深度学习)含全部Python工程源码及模型+训练数据集

    目录 前言 总体设计 系统整体结构图 系统流程图 孪生神经网络结构图 运行环境 Python 环境 TensorFlow 环境 模块实现 1 数据预处理 2 创建模型并编译 3 模型训练及保存 4 模型应用 系统测试 1 训练准确率 2 测
  • 软件测试管理方法(十一)——软件评审

    0 基本概念 工作 产品指软生命周期中各种产出物 包括各种文档 代码等 1 目的 从多方角度检查和评估每个阶段工作产品的合格情况 确保每个阶段的产出都是符合既定要求的 从而减少软件开发周期 包括项目周期 的返工现象 静态地测试程序中可能存在
  • LInux 锂电池驱动分析

    锂电池的驱动程序要实现以 下五个功能 1 可以自动检测到当前给电 池充电的是USB还 是AC 2 组织过大的充电电流 3 坏电池检测 4 死亡温度的检测 5 电池电压的测量 当我们要写一个锂 电池的驱动程序 的时候 首先 要知道内核提 供给
  • SpringBoot+Shiro实现免密登录

    1 自定义登录认证规则 import org apache shiro authc UsernamePasswordToken public class EasyUsernameToken extends UsernamePasswordT
  • DM6446的视频前端VPFE驱动之ioctl控制(视频缓存区,CCDC,decoder)解析之一

    本文均属自己阅读源码的点滴总结 转账请注明出处谢谢 欢迎和大家交流 qq 1037701636 email 200803090209 zjut com gzzaigcn2012 gmail com 在这里分析驱动的ioctl的内容时 需要结
  • Feature Pyramid Networks for Object Detection 论文笔记

    论文地址 Feature Pyramid Networks for Object Detection 前言 这篇论文主要使用特征金字塔网络来融合多层特征 改进了CNN特征提取 论文在Fast Faster R CNN上进行了实验 在COCO
  • 本地jar包上传的maven仓库,引用jar包中的pom依赖无法下载

    新项目开发公共组件 上传到公司maven仓库 记一次本地项目打包 上传到公司maven仓库的坑 mvn deploy deploy file DgroupId com test 分组 DartifactId test jar名称 Dvers
  • 【cuda】——cuda,opencv混合编程

    思路来自 https www cnblogs com dwdxdy p 3528711 html 但是其cuda源码是有问题的 没有cmakelists txt 背景 采用cuda gpu交换opencv图像的 r b通道 0 代码 mai
  • 恒生ufx接口转变成CTP接口

    由于当初自己的程序是对接ctp接口 里面大量使用了ctp的东西 但最近又要对接恒生的系统 想着不改整个程序 把ufx接口封装成ctp的接口形式 这样上层的业务逻辑都不用改了 已实现的主要功能 ReqUserLogin ReqOrderIns
  • C++的mutable

    一 介绍 mutable的中文意思是 可变的 易变的 正好与const相反 在C 中 mutable也是为了突破const的限制而设置的 被mutable修饰的变量 将永远处于可变的状态 即使在一个const函数中 二 用法 如果类的成员函
  • Nginx 动态负载均衡

    Nginx 负载均衡 动态实现 1 概览 1 传统配置实现的负载均衡 在加减服务器的时候 会遇到下面的问题 1 配置文件是默认地址 则需要重载配置文件 nginx s reload 加载配置文件流程 1 主进程通知worker进程进行重启
  • 一文了解什么是字节对齐(超详细)

    目录 1 什么是字节对齐 2 空类 3 带虚函数的类 32位机器 64位机器 1 什么是字节对齐 得分点 什么是内存对齐 内存对齐的原因 内存对齐的规则 标准回答 什么是内存对齐 现代计算机中内存空间都是按照 字节 byte 划分的 从理论