2. C++ 内存对齐

C++ 内存对齐

内存对齐是编译器为了便于CPU快速访问而采用的一项技术

我们先从一个例子开始,对下面的类(或者结构体)

class node{    char c;    int i;    short s;
}no;

sizeof(no)的值是多少呢,如果你的回答是7(1+4+2),那么你应该认真阅读下面的内容。可以在编译器上试试,输出的结果是12,这就是内存对齐的结果。

为什么要进行内存对齐呢?

平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。

性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问

编译器一般按照几个字节对齐呢?本文中两个编译器默认按照类中最大类型长度来对齐,我么也可以使用语句#pragma pack(i)(i = 1,2,4,8,16)来设置对齐字节数目,vs还可以在项目属性-配置属性-c/c+±代码生成-结构成员对齐设置。

对齐规则如下:

  1. 如果设置了内存对齐为 i 字节,类中最大成员对齐字节数为j,那么整体对齐字节n = min(i, j) (某个成员的对齐字节数定义:如果该成员是c++自带类型如int、char、double等,那么其对齐字节数=该类型在内存中所占的字节数如果该成员是自定义类型如某个class或者struct,那个它的对齐字节数 = 该类型内最大的成员对齐字节数《详见实例4》)

  2. 每个成员对齐规则:类中第一个数据成员放在offset为0的位置对于其他的数据成员(假设该数据成员对齐字节数为k),他们放置的起始位置offset应该是 min(k, n) 的整数倍

  3. 整体对齐规则:最后整个类的大小应该是n的整数倍

  4. 当设置的对齐字节数大于类中最大成员对齐字节数时,这个设置实际上不产生任何效果(实例2);当设置对齐字节数为1时,类的大小就是简单的把所有成员大小相加

我们通过以下几个实例来分析

实例1:(没有指定对齐字节,则n = 最大成员(int i)的大小4)

class node{    char c;   //放在位置0,位置区间[0]    int i;      //4 = n, 那么放置起始位置应该是4的倍数,即4,位置区间为[4~7]    short s; //2 < n,那么放置起始位置应该是2的倍数,即8,位置区间为[8~9]
}

此时成员共占用[0~9]10个字节,还要整体对齐,大小应该是4的倍数,即12

实例2:(假设指定对齐字节为8,那么n = min(8,4) = 4)

class node{   int i; //放在位置0,位置区间[0~3]    char c; //1 < n, 那么放置起始位置应该是1的倍数,即4,位置区间为[4]    short s; //2 < n,那么放置起始位置应该是2的倍数,即6,位置区间为[6~7
}

成员共占据[0~7]8个字节,刚好是4的倍数,因此大小是8

实例3:(假设指定对齐字节是2,则n = min(2,4) = 2)

class node{    char c; //放在位置0,位置区间[0]    int i; //4 > n, 那么放置起始位置应该是2的倍数,即2,位置区间为[2~5]    short s; //2 = n,那么放置起始位置应该是2的倍数,即6,位置区间为[6~7]
}

此时成员共占用[0~7]8个字节,刚好是4的倍数,因此大小是8

实例4:(按照默认设置)

class temp{    char c;    int i;    short s1;
};

由实例1可知,默认对齐情况下,temp的大小是12,temp的对齐字节数是:三个成员取最大的,即为4;

对于node,n = 其三个成员对齐字节数取最大,即等于t的对齐字节数,也就是 4。

class node{    char c; //放在位置0,位置区间[0]    temp t; //4(temp的对齐字节数) = n, 那么放置起始位置应该是4的倍数,即4,位置区间为[4~15]    short s; //2 < n,那么放置起始位置应该是2的倍数,即16,位置区间为[16~17]
}

此时成员共占用[0~17]18个字节,还要整体对齐,大小应该是4的倍数,因此大小是20

实例5:(默然设置)

对于node,n = 其三个成员对齐字节数取最大,即等于d的对齐字节数,也就是 8。

class node{    temp t; //放在位置0,位置区间[0~11]    double d; //8(temp的对齐字节数) = n, 那么放置起始位置应该是8的倍数,即16,位置区间为[16~23]    short s; //2 < n,那么放置起始位置应该是2的倍数,即24,位置区间为[24~25]
}

此时成员共占用[0~25]26个字节,还要整体对齐,大小应该是8的倍数,因此大小是32.

类继承时的内存对齐

考虑如下类

class A{    int i;    char c1;
}class B:public A{    char c2;
}class C:public B{    char c3;
}

sizeof©结果是多少呢,gcc和vs给出了不同的结果,分别是8、16

gcc中:C相当于把所有成员i、c1、c2、c3当作是在一个class内部,(先继承后对齐)

vs中:对于A,对齐后其大小是8;对于B,c2加上对齐后的A的大小是9,对齐后就是12;对于C,c3加上对齐后的B大小是13,再对齐就是16 (先对齐后继承)

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

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

相关文章

C++命名规则

如果想要有效的管理一个稍微复杂一点的体系&#xff0c;针对其中事物的一套统一、带层次结构、清晰明了的命名准则就是必不可少而且非常好用的工具。 活跃在生物学、化学、军队、监狱、黑社会、恐怖组织等各个领域内的大量有识先辈们都曾经无数次地以实际行动证明了以上公理的…

【Java Web基础】一些网页设计基础(三)

文章目录 1. 导航栏样式进一步调整2. 入驻企业信息展示栏2.1 Title设置2.2 具体信息添加 3. 轮播图4. 注册登录按钮及其他信息5. 一些五颜六色的、丰富视觉效果的中间件…… 1. 导航栏样式进一步调整 这种导航栏&#xff0c;选中的时候字体变蓝色&#xff0c;可能还是不够美观&…

【项目实践】VS配置Qt

文章目录 前言版本使用具体步骤1&#xff09;安装Qt或者添加删除组件2&#xff09;VS安装Qt Visual Studio Tools 如何使用遇到的问题双击ui文件编辑报错 前言 最近因为一个项目&#xff0c;需要使用Qt&#xff0c;本来想使用Python的&#xff0c;但是由于另外一个第三方的库是…

C 多维数组

C 语言支持多维数组。多维数组声明的一般形式如下&#xff1a; type name[size1][size2]...[sizeN];例如&#xff0c;下面的声明创建了一个三维 5 . 10 . 4 整型数组&#xff1a; int threedim[5][10][4];二维数组 多维数组最简单的形式是二维数组。一个二维数组&#xff0c…

Qt/C++监控推流设备推流/延迟极低/实时性极高/rtsp/rtmp推流/hls/flv/webrtc拉流/调整分辨率降低带宽

一、前言 算下来这个推流的项目作品写了有四年多了&#xff0c;最初第一个版本只有文件点播的功能&#xff0c;用的纯QTcpSocket通信实现&#xff0c;属于比较简单的功能。由于文件点播只支持文件形式的推流&#xff0c;不支持网络流或者本地设备采集&#xff0c;所以迫切需要…

2024Python计算机二级7

带符号的定点数之中&#xff0c;正数的原码、补码和反码均相同&#xff0c;负数的反码是对该数的原码除符号位外各位取反&#xff0c;补码是在该数的反码的最后&#xff08;即最右边&#xff09;一位上加1&#xff1b;不管是正数还是负数&#xff0c;其补码的符号位取反即是偏移…

每日三个JAVA经典面试题(十八)

1.volatile 关键字的作用 在Java中&#xff0c;volatile关键字用于声明变量&#xff0c;以确保该变量的更新对所有线程都是可见的&#xff0c;即当一个线程修改了一个volatile变量的值&#xff0c;这个新值对于其他线程来说是立即得知的。volatile关键字有两个主要作用&#x…

GEE高阶案例——Landsat/Sentinel/MODIS影像进行缨帽变换一行代码实现

本教程的主要目的是利用eemont中的tasseledCap()的函数进行缨帽变换实现。 在 eemont 中,可使用扩展到 ee.Image 和 ee.ImageCollection 对象的 tasseledCap 方法计算缨帽亮度、绿度和湿度组件。只需从支持的平台加载图像,然后使用 tasseledCap 添加分量带即可。 代码: !p…

H6603实地架构降压芯片100V耐压 80V 72V 60V 48V单片机/模块供电应用

H6603 是一款内置功率 MOSFET降压开关转换器。在宽输入范围内&#xff0c;其最大持续输出电流 0.8A&#xff0c;具有极好的负载和线性调整率。电流控制模式提供了快速瞬态响应&#xff0c;并使环路更易稳定。故障保护包括逐周期限流保护和过温保护。H6603 最大限度地减少了现有…

智能驾驶域控制器行业介绍

汽车智能驾驶功能持续高速渗透&#xff0c;带来智能驾驶域控制器市场空间快速增 长。智驾域控制器是智能驾驶决策环节的重要零部件&#xff0c;主要功能为处理感知 信息、进行规划决策等。其核心部件主要为计算芯片&#xff0c;英伟达、地平线等芯 片厂商市场地位突出。随着消费…

ECharts5 应用篇

跨平台方案 服务端渲染 服务端 SVG 渲染 5.3.0 里新引入了零依赖的服务端 SVG 字符串渲染方案&#xff1a; // 服务端代码 const echarts require(echarts);// 在 SSR 模式下第一个参数不需要再传入 DOM 对象 let chart echarts.init(null, null, {renderer: svg, // 必须使用…

(C语言) print输出函数系列介绍

(C语言) print输出函数系列介绍 文章目录 (C语言) print输出函数系列介绍前言输出系列函数&#x1f5a8;️printf&#x1f5a8;️sprintf & snprintf&#x1f5a8;️fprintf&#x1f5a8;️vprintf&#x1f5a8;️dprintf&#x1f5a8;️puts&#x1f5a8;️fputs&#x1f…

Spring6--IOC反转控制 / 基于XML管理bean

1. 容器IOC 先理解概念&#xff0c;再进行实际操作。概念比较偏术语化&#xff0c;第一次看可能看不懂&#xff0c;建议多看几遍&#xff0c;再尝试自己独立复述一遍&#xff0c;效果会好些 1.1. IOC容器 1.1.1. 控制反转&#xff08;IOC&#xff09; IOC (Inversion of Con…

AL379芯片和AL383芯片是一款DC-DC升压芯片IC

首先&#xff0c;我们来了解HU6283芯片5V升压12V芯片的工作原理。这种芯片通常采用开关电源技术&#xff0c;通过高频开关控制&#xff0c;将5V的输入电压转换为12V的输出电压。开关电源技术具有高效、稳定、体积小等优点&#xff0c;因此在电子设备中得到了广泛应用。5V升压12…

各种小功能

目录 Python在指定目录创建多个相似命名的文件夹 Python 在指定目录创建多个相似命名的文件夹

Python 使用requests模块 执行Web API调用 获取网站数据并可视化

import requests#执行web api调用&#xff0c;并将响应存储在response_dict字典中 urlhttps://api.github.com/search/repositories?qlanguage:python&sortstars headers{Accept:application/vnd.github.v3json} rrequests.get(url,headersheaders) print(fStatus code:{r…

软件测评中心分享:软件鉴定测试与验收测试有什么联系和区别?

1、软件鉴定测试   软件鉴定测试是在软件开发完成后进行的一个核心环节&#xff0c;是通过对软件进行功能性、性能、安全性等方面的综合测试&#xff0c;来验证软件是否符合规定的需求和标准。 2、软件验收测试   软件验收测试是软件开发工作结束后的最后一个环节&#xf…

并发编程所需的底层基础

一、计算机运行的底层原理 1.多级层次的存储结构 ①:辅存 固态盘不是主要的应用对象&#xff0c;因为固态盘的使用次数是有限的&#xff0c;无法支撑高并发场景 磁盘存储的最基本原理是电生磁。 磁盘的磁道里边有很多的磁颗粒&#xff0c;磁颗粒上边有一层薄膜为了防止磁点氧…

MySQL连接池和MySQL永久连接(长连接)在数据库连接管理方面都有其独特的优缺点。swoole pdopool实现

MySQL连接池的优点&#xff1a; 资源重用&#xff1a;连接池中的连接可以被多个请求共享&#xff0c;避免了频繁创建和释放连接所引起的大量性能开销。这有助于减少内存碎片以及数据库临时进程或线程的数量&#xff0c;从而增进系统运行环境的平稳性。更快的系统响应速度&…

5G网络架构与组网部署03--5G网络组网部署

1. SA组网与NSA组网 &#xff08;1&#xff09;NSA 非独立组网&#xff1a;终端同时接入4G基站和5G基站&#xff0c;只能实现5G部分功能 &#xff08;2&#xff09;SA组网【最终目标】&#xff1a;5G基站可以单独提供服务&#xff0c;接入的是5G核心网 区别&#xff1a;同一时间…