1. 内存对齐的概念

内存对齐是一个数据类型所能存放的内存地址的属性。这个属性是一个无符号整数,并且这个整数必须是2的N次方(1、2、4、8、、、1024、、、)。

例如当我们说一个数据类型的内存对齐为8时,是指这个数据类型所定义出来的所有变量的内存地址都是8的倍数。

2. 自然对齐的概念

当一个基本数据类型的对齐属性和这个数据类型的大小相等时,称为自然对齐。例如一个4字节大小的int型数据,默认情况下字节对齐是4。

3. 为什么需要内存对齐?

1) 并不是每一个硬件平台都能随便访问任意位置的内存的。某些平台(例如Alpha等)若读取的数据未内存对齐,将拒绝访问或抛出异常。

2)将一个int放在奇数内存(例如1)位置上,如果想把4个字节读出来,32位CPU需要读取两次。如下例子所示:

如果按照4字节对齐后,一次就可以读取出来了,提升了效率。

4. 内存对齐示例

#include <iostream>
using namespace std;struct
{int i;char c1;char c2;
}Test1;struct {char c1;int i;char c2;
}Test2;struct {char c1;char c2;int i;
}Test3;int main()
{cout << sizeof(Test1) << endl;cout << sizeof(Test2) << endl;cout << sizeof(Test3) << endl;system("pause");return 0;
}

执行结果:

8

12

8

本例测试环境为vs2015,默认4字节对齐,分析如下所示:

5. 堆内存对齐

malloc一般使用当前平台默认的最大内存对齐数对齐内存,比如,MSVC在32位下一般为8字节对齐,64位下则是16字节对齐。如果我们自定义的内存对齐超出了这个范围,则不能直接使用malloc获取内存。

但当我们有需求需要分配一块具有特定内存对齐的内存块时,在MSVC下应使用_aligned_malloc,gcc下一般使用memalogn等函数。

实现一个简易的aligned_malloc:

inline void* aligned_malloc(size_t size, size_t alignment)
{//检查alignment是否为2^Nassert(!(alignment & (alignment - 1)));//计算出最大的offset,sizeof(void*)是为了存储原始指针地址size_t offset = sizeof(void*) + (--alignment);//分配一块带offset的内存char *p = static_cast<char*>(malloc(offset + size));if (!p)return nullptr;//通过"& (~alignment)"把多计算的offset减掉void* r = reinterpret_cast<void*>(reinterpret_cast<size_t>(p + offset) & (~alignment));//将r当作一个指向void*的指针,在r当前地址前面放入原始地址static_cast<void**>(r)[-1] = p;//返回经过对齐的内存地址return r;
}inline void align_free(void* p)
{//还原回原始地址,并freefree(static_cast<void**>(p)[-1]);
}

6. 利用alignas指定内存对齐的大小

例如:

alignas(32) long long a = 0;#define XX 1
struct alignas(XX)MyStruct {};

注意:alignas只能改大不能改小,如果需要改小,需要使用#prama pack(n),n为对齐字节数。

c++11中与#prama等价的为_Prama(微软暂不支持,vs中暂不能使用);


_Pragma("pack(1)")
struct MyStruct
{char a;int b;short c;long d;
};
_Pragma("pack()")

7. 利用alignof和std::alignment_of获取内存对齐的大小

struct MyStruct
{char c;int a;double b;
};int main()
{//获取内存对齐的大小cout << alignof(MyStruct) << endl;  //8int alignSize = std::alignment_of<MyStruct>::value;cout << alignSize << endl;  //8system("pause");return 0;
}

8. std::max_align_t和std::align操作符

1)std::max_align_t用来返回当前平台的最大默认内存对齐类型。

cout << alignof(std::max_align_t) << endl;

2)std::align用来在一大块内存当中获取一个符合指定内存要求的地址。

std::align的原型为:

void* align( std::size_t alignment,

std::size_t size,
             void*& ptr,

std::size_t& space );

char buf[] = "-----------------";
void* p = buf;
std::size_t space = sizeof(buf) - 1;
std::align(alignof(int), sizeof(char), p, space);

在buf这个大内存块中,指定内存对齐为slignof(int),找一块sizeof(char)大小的内存,并且在找到这块内存后将地址放入p,将buf从p开始的长度当入space。

c++11总结10——内存对齐相关推荐

  1. C语言基础知识之define宏定义表达式,undef,内存对齐,a和a的区别,数组知识点,int (*)[10] p,二维数组参数与二维指针参数,函数指针数组,常见的内存错误及对策

    一.用define宏定义表达式 1.定义一年有多少秒: #define SEC_A_YEAR 60*60*24*365 //上述描述不可靠,没有考虑到在16位系统下把这样一个数赋给整型变量的时候可能会 ...

  2. 内存对齐与sizeof

    一.一个例子 #include <iostream>  using namespace std;  struct X1  {    int i;//4个字节    char c1;//1个 ...

  3. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

  4. NumPy-快速处理数据--ndarray对象--多维数组的存取、结构体数组存取、内存对齐、Numpy内存结构...

    本文摘自<用Python做科学计算>,版权归原作者所有. 上一篇讲到:NumPy-快速处理数据--ndarray对象--数组的创建和存取 接下来接着介绍多维数组的存取.结构体数组存取.内存 ...

  5. struc,union,class的内存对齐方式

    首先思考一个问题:int,short,char的struct,这几个数应该怎么放,内存最小 strct ts { int a; short b; char c; }; 这样放最小,为8,这样放置,只会 ...

  6. 大小端、位段和内存对齐

    关于C++中的大小端.位段(惑位域)和内存对齐 来源: ♂戚建建㊣的日志 听到好几个朋友说到去一些公司做面试,总是遇到关于大小端.位段(或者叫位域)和内存对齐的考题,然后就不知所措了.虽然我认为很多开 ...

  7. 总结面试时没有回答上的内存对齐问题

    前两天面试某公司时,没有回答上的一个问题,总结如下,以供参考. 问:下面这个结构类型的实例变量占用多少内存: struct struct1 {     int i;     short j;     ...

  8. C++ 内存对齐 及 引用是否真的节省内存的一点思考

    文章目录 1. 内存对齐 2. 递归中的内存对齐 3. C++引用的本质 4. 致谢 1. 内存对齐 通过以下语句,获取变量的占用内存打下: cout << "size of i ...

  9. 内存对齐分配策略(含位域模式)

    1:内存对齐定义:     现在使用的计算机中内存空间都是按照字节划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但是实际上计算机系统对于基本数据类型在内存 中的存放位置都有限制,要求 ...

最新文章

  1. “智享未来 知行合一”,开为科技AI产品发布会于2月6日召开
  2. opencv源码解析之(6):hog源码分析
  3. 普通行列转换(交叉表,横表变列表)
  4. linux6.4 dns 主从,dns正反解析与主从复制文件同步
  5. 每天一道LeetCode-----逆序链表
  6. 【VB测绘程序设计】第二章 VB测绘程序基础
  7. 三个好用的并发工具类
  8. oracle dblink 验证,Oracle DBLINK 简单使用
  9. 程序员到底会不会修电脑?
  10. 高效程序员的45个习惯の欲速则不达
  11. 树——二叉树的深层特性
  12. ENVI5.4 新增图像分类介绍
  13. Kafka 入门教程之一: 安装
  14. C语言课程设计|通讯录管理系统(含完整代码)
  15. 全志(Allwinner) A40i使用千兆网的配置
  16. 项目质量管理—七种基本质量工具
  17. 谷歌浏览器设置默认Flash
  18. 麦子学院IT资源,web前端,UI设计,Java全套,IOS,android,产品经理,pyhton,网络安全,运维
  19. 2003系统服务器不设置密码,服务器2003怎么设置密码
  20. 关于正向级数收敛而它的平方也收敛的证明

热门文章

  1. vue中动态请求URL乱码
  2. java数据库连接池满了怎么查
  3. 用友U8案例教程应收管理前台操作
  4. 从天龙八部论嵌入式行业中个人与企业的核心竞争力
  5. Linux字符设备驱动详解四(使用自属的xbus驱动总线)
  6. SendMessage和PostMessage的用法
  7. 小厂前端实习生面经| 深圳
  8. 家乡景区介绍网页模板
  9. 计算机中的电介质,计算机科学技术-第三章静电场中的电介质.doc
  10. python字典对象的方法返回字典的值列表_python对象转字典的两种实现方式示例