C++中的内存对齐实例详解

C++中的内存对齐实例详解

内存对齐

在我们的程序中,数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度。

我们还是先来看一段简单的程序:

程序一

 #include <iostream>
 using namespace std;

 struct X1
 {
  int i;//4个字节
  char c1;//1个字节
  char c2;//1个字节
 };

 struct X2
 {
  char c1;//1个字节
  int i;//4个字节
  char c2;//1个字节
 };

 struct X3
 {
  char c1;//1个字节
  char c2;//1个字节
  int i;//4个字节
 };
 int main()
 {
   cout<<"long "<<sizeof(long)<<"\n";
   cout<<"float "<<sizeof(float)<<"\n";
   cout<<"int "<<sizeof(int)<<"\n";
   cout<<"char "<<sizeof(char)<<"\n";

   X1 x1;
   X2 x2;
   X3 x3;
   cout<<"x1 的大小 "<<sizeof(x1)<<"\n";
   cout<<"x2 的大小 "<<sizeof(x2)<<"\n";
   cout<<"x3 的大小 "<<sizeof(x3)<<"\n";
   return 0;
 }

这段程序的功能很简单,就是定义了三个结构X1,X2,X3,这三个结构的主要区别就是内存数据摆放的顺序,其他都是一样的,另外程序输入了几种基本类型所占用的字节数,以及我们这里的三个结构所占用的字节数。

这段程序的运行结果为:

 long 4
 float 4
 int 4
char 1
x1 的大小 8
x2 的大小 12
x3 的大小 8

结果的前面四行没有什么问题,但是我们在最后三行就可以看到三个结构占用的空间大小不一样,造成这个原因就是内部数据的摆放顺序,怎么会这样呢?

下面就是我们需要讲的内存对齐了。

内存是一个连续的块,我们可以用下面的图来表示,  它是以4个字节对一个对齐单位的:

图一

让我们看看三个结构在内存中的布局:

首先是 X1,如下图所示

X1 中第一个是 Int类型,它占有4字节,所以前面4格就是满了,然后第二个是char类型,这中类型只占一个字节,所以它占有了第二个4字节组块中的第一格,第三个也是char类型,所以它也占用一个字节,它就排在了第二个组块的第二格,因为它们加在一起大小也不超过一个块,所以他们三个变量在内存中的结构就是这样的,因为有内存分块对齐,所以最后出来的结果是8,而不是6,因为后面两个格子其实也算是被用了。

再次看看X2,如图所示

X2中第一个类型是Char类型,它占用一个字节,所以它首先排在第一组块的第一个格子里面,第二个是Int类型,它占用4个字节,第一组块已经用掉一格,还剩3格,肯定是无法放下第二Int类型的,因为要考虑到对齐,所以不得不把它放到第二个组块,第三个类型是Char类型,跟第一个类似。所因为有内存分块对齐,我们的内存就不是8个格子了,而是12个了。

再看看X3,如下图所示:

关于X3的说明其实跟X1是类似的,只不过它把两个1个字节的放到了前面,相信看了前面两种情况的说明这里也是很容易理解的。

唉,写到这手都累了,关键是要画图,希望通过此文能让你理解内存对齐的基本概念,如果有问题,请留言。

感谢阅读,希望能帮助到大家,谢谢大家对本站的支持,如有疑问,请留言,共同进步!

(0)

相关推荐

  • C++动态分配和撤销内存以及结构体类型作为函数参数

    C++动态分配内存(new)和撤销内存(delete) 在软件开发过程中,常常需要动态地分配和撤销内存空间,例如对动态链表中结点的插入与删除.在C语言中是利用库函数malloc和free来分配和撤销内存空间的.C++提供了较简便而功能较强的运算符new和delete来取代malloc和free函数. 注意: new和delete是运算符,不是函数,因此执行效率高. 虽然为了与C语言兼容,C++仍保留malloc和free函数,但建议用户不用malloc和free函数,而用new和delete运算

  • 深入理解c/c++ 内存对齐

    内存对齐,memory alignment.为了提高程序的性能,数据结构(尤其是栈)应该尽可能地在自然边界上对齐.原因在于,为了访问未对齐的内存,处理器需要作两次内存访问:然而,对齐的内存访问仅需要一次访问.内存对齐一般讲就是cpu access memory的效率(提高运行速度)和准确性(在一些条件下,如果没有对齐会导致数据不同步现象).依赖cpu,平台和编译器的不同.一些cpu要求较高(这句话说的不准确,但是确实依赖cpu的不同),而有些平台已经优化内存对齐问题,不同编译器的对齐模数不同.总

  • C/C++语言中结构体的内存分配小例子

    当未用 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度对齐:当使用了 #pragma 指令指定编译器的对齐位数时,结构体按最长宽度的数据成员的宽度和 #pragma 指令指定的位数中的较小值对齐. #pragma 指令格式如下所示:#pragma pack(4)     // 或者 #pragma pack(push, 4) 举例如下:(机器字长为 32 位)    struct    {        char a;    }test;    printf("%d

  • 关于C++内存中字节对齐问题的详细介绍

    一.什么是字节对齐计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 二.对齐的作用和原因:1.平台原因(移植原因):不是所有的硬件平台都能访问任意地址上的任意数据的:某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常.各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型

  • C++对象内存分布详解(包括字节对齐和虚函数表)

    1.C++对象的内存分布和虚函数表: C++对象的内存分布和虚函数表注意,对象中保存的是虚函数表指针,而不是虚函数表,虚函数表在编译阶段就已经生成,同类的不同对象中的虚函数指针指向同一个虚函数表,不同类对象的虚函数指针指向不同虚函数表. 2.何时进行动态绑定: (1)每个类对象在被构造时不用去关心是否有其他类从自己派生,也不需要关心自己是否从其他类派生,只要按照一个统一的流程:在自身的构造函数执行之前把自己所属类(即当前构造函数所属的类)的虚函数表的地址绑定到当前对象上(一般是保存在对象内存空间

  • C语言、C++内存对齐问题详解

    这也可以? 复制代码 代码如下: #include <iostream> using namespace std;   struct Test_A {      char a;      char b;      int c; };   struct Test_B {      char a;      int c;      char b; };   struct Test_C {      int c;      char a;      char b; };   int main() {

  • C++面试题之结构体内存对齐计算问题总结大全

    前言 本文给大家介绍的是关于C++结构体内存对齐计算的相关内容,内存对齐计算可谓是笔试题的必考题,但是如何按照计算原则算出正确答案一开始也不是很容易的事,所以专门通过例子来复习下关于结构体内存对齐的计算问题.话不多说,来一起看看详细介绍吧. 编译环境:vs2015 对齐原则: 原则1:数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个

  • C++中的内存对齐实例详解

    C++中的内存对齐实例详解 内存对齐 在我们的程序中,数据结构还有变量等等都需要占有内存,在很多系统中,它都要求内存分配的时候要对齐,这样做的好处就是可以提高访问内存的速度. 我们还是先来看一段简单的程序: 程序一 #include <iostream> using namespace std; struct X1 { int i;//4个字节 char c1;//1个字节 char c2;//1个字节 }; struct X2 { char c1;//1个字节 int i;//4个字节 ch

  • C语言内存对齐实例详解

    本文详细讲述了C语言程序设计中内存对其的概念与用法.分享给大家供大家参考之用.具体如下: 一.字节对齐基本概念 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这就需要各种类型数据按照一定的规则在空间上排列,而不是顺序的一个接一个的排放,这就是对齐. 对齐的作用和原因:各个硬件平台对存储空间的处理上有很大的不同.一些平台对某些特定类型的数据只能从某些特定地址开始存取.比如有些架构的C

  • Android 中的两端对齐实例详解

    在android中的webview中,可以对文本内容进行对齐,具体方法如下 public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String htmlText = " %s "

  • IOS 调整内存中的图片大小实例详解

    IOS 调整内存中的图片大小实例详解 在从网路download图片,或者从相册读取图片的时候,如果ImageView的本身就是固定的300*200,那么载入2000*2000的图片是很浪费内存的. 2000*2000的内存占用是2000*2000*4bit 以下两个函数可以用来创建一个新的按照固定大小的图片.简单来说,就是Core Graphics来创建一个bitmap,然后生成一个图片. - (UIImage*)imageWithImage:(UIImage*)image scaledToSi

  • JSP中out对象的实例详解

    JSP中out对象的实例详解 一 什么是缓冲区 缓冲区:Buffer,所谓缓冲区就是内存的一块区域用来保存临时数据. 二 out对象 out对象是JspWrite类的实例,是向浏览器输出内容常用的对象. 三 常用方法 四 实例 <%@ page language="java" import="java.util.*" contentType="text/html; charset=utf-8"%> <% String path

  • Java 中This用法的实例详解

     Java 中This用法的实例详解 用类名定义一个变量的时候,定义的只是一个引用,外面可以通过这个引用来访问这个类里面的属性和方法. 那们类里面是够也应该有一个引用来访问自己的属性和方法纳? 呵呵,Java提供了一个很好的东西,就是 this 对象,它可以在类里面来引用这个类的属性和方法.先来个简单的例子: public class ThisDemo { String name="Mick"; public void print(String name){ System.out.pr

  • java中Spring Security的实例详解

    java中Spring Security的实例详解 spring security是一个多方面的安全认证框架,提供了基于JavaEE规范的完整的安全认证解决方案.并且可以很好与目前主流的认证框架(如CAS,中央授权系统)集成.使用spring security的初衷是解决不同用户登录不同应用程序的权限问题,说到权限包括两部分:认证和授权.认证是告诉系统你是谁,授权是指知道你是谁后是否有权限访问系统(授权后一般会在服务端创建一个token,之后用这个token进行后续行为的交互). spring

  • Linux中对MySQL优化实例详解

    Linux中对MySQL优化实例详解 vim /etc/my.cnf以下只列出my.cnf文件中[mysqld]段落中的内容,其他段落内容对MySQL运行性能影响甚微,因而姑且忽略. [mysqld] port = 3306 serverid = 1 socket = /tmp/mysql.sock skip-locking 避免MySQL的外部锁定,减少出错几率增强稳定性. skip-name-resolve 禁止MySQL对外部连接进行DNS解析,使用这一选项可以消除MySQL进行DNS解析

  • PHP中递归的实现实例详解

    递归的定义 递归(http:/en.wikipedia.org/wiki/Recursive)是一种函数调用自身(直接或间接)的一种机制,这种强大的思想可以把某些复杂的概念变得极为简单.在计算机科学之外,尤其是在数学中,递归的概念屡见不鲜.例如:最常用于递归讲解的斐波那契数列便是一个极为典型的例子,而其他的例如阶层(n!)也可以转化为递归的定义(n! = n*(n-1)!).即使是在现实生活中,递归的思想也是随处可见:例如,由于学业问题你需要校长盖章,然而校长却说"只有教导主任盖章了我才会盖章&

  • Java语言中的内存泄露代码详解

    Java的一个重要特性就是通过垃圾收集器(GC)自动管理内存的回收,而不需要程序员自己来释放内存.理论上Java中所有不会再被利用的对象所占用的内存,都可以被GC回收,但是Java也存在内存泄露,但它的表现与C++不同. JAVA中的内存管理 要了解Java中的内存泄露,首先就得知道Java中的内存是如何管理的. 在Java程序中,我们通常使用new为对象分配内存,而这些内存空间都在堆(Heap)上. 下面看一个示例: public class Simple { public static vo

随机推荐