• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >C语言 > 深入内存对齐的详解

深入内存对齐的详解

作者: 字体:[增加 减小] 来源:互联网 时间:2017-05-28

通过本文主要向大家介绍了内存参数详解,内存条参数详解,内存详解,stm32内存管理详解,内存条详解等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

1.引子

    在结构中,编译器为结构的每个成员按其自身的自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

    例如,下面的结构各成员空间分配情况(假设对齐方式大于2字节,即#pragma pack(n), n = 2,4,8...下文将讨论#pragmapack()):

    好了,下面说说#pragma pack:

2.#pragma pack()

    该预处理指令用来改变对齐参数。在缺省情况下,C编译器为每一个变量或数据单元按其自然对界条件分配空间。一般地,可以通过下面的方法来改变缺省的对齐参数:

     · 使用伪指令#pragma pack (n),C编译器将按照n字节对齐。

     · 使用伪指令#pragma pack (),取消自定义字节对齐方式。

也可以写成:

#pragma pack(push,n)

#pragma pack(pop)

#pragma pack (n)表示每个成员的对齐单元不大于n(n为2的整数次幂)。这里规定的是上界,只影响对齐单元大于n的成员,对于对齐字节不大于n的成员没有影响。其实从字面意思,pack是“包裹,打包”的意思,#pragma pack(n)规定n个字节是一个“包裹”,个人认为实在不理解的话可以认为处理器一次性可以从内存中读/写n个字节,这样好理解。对于大小小于n的成员,当然是按照自己的对齐条件对齐,因为不论怎么放都可以一次性取出。对于对齐条件大于n个字节的成员,成员按照自身的对齐条件对齐和按照n字节对齐需要相同的读取次数,但按照n字节对齐节省空间,何乐而不为呢。可以参考我上面提到的<解析内存对齐 Data alignment: Straighten up and fly right的详解>。下面是一位大牛的观点,和我说的是一个意思:

   All it means is that each member of it will require alignment no greater than n.It doesn't mean that each member will have alignment requirement n.Notice, after all, it's called pack and not align for a reason-- precisely because it controls packing, not alignment.

另外,GNU C还有如下的一种方式:

     · __attribute__((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

     · __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。

以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。

3.结构体内成员如何找出自己的位置

首先遵循以下规则:

1.  每个成员分别取自己的对齐方式和#pragma pack指定的对齐参数二者的较小值作为自己的对齐方式。

2.  复杂类型(如结构)的对齐方式是该类型声明时所使用的对齐方式,或者说是声明时它的所有成员使用的对齐参数的最大值,最后和此时的#pragma pack指定的对齐参数二者取极小值。大牛是这么说的:

The documentation for #pragma pack(n) says that "The alignment of a member will be on a boundary that is either a multiple of n or a multiple of the size of the member,whichever is smaller". However I think this is incorrect; the docs should say that the alignment of a member will be on a boundary that is either a multiple of n or the alignment requirement of the member, whichever is smaller.

3.  对齐后的长度必须是成员中最大的对齐参数(不是成员的大小)的整数倍,这样在处理数组时可以保证每一项都边界对齐。

4.  对于数组,比如:char a[3];这种,它的对齐方式和分别写3个char是一样的。也就是说它还是按1个字节对齐.

        如果写: typedef char Array3[3];

        Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度。

5.  不论类型是什么,对齐的边界一定是1,2,4,8,16,32,64....中的一个。

看一个简单的例子:

    也就是说上面虽然指定了按8字节对齐,但并不是所有的成员都是以8字节对齐。其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里是8字节)中较小的一个对齐。并且结构的长度必须为所用过的所有对齐参数的整数倍(只要是最大的对齐参数的整数倍即可),不够就补空字节(视编译器而定)。

    S1中,成员a是2字节默认按2字节对齐,指定对齐参数为8,这两个值中取2,a按2字节对齐;成员b是4个字节,默认是按4字节对齐,这时就按4字节对齐,a后补2个字节后存放b,所以sizeof(S1)应该为8。8是4的倍数,满足上述的第3条规则。

    S2中,c和S1中的a一样,按2字节对齐,而d是个结构,它是8个字节,它按什么对齐呢?对于结构来说,它的默认对齐方式就是该结构定义(声明)时它的所有成员使用的对齐参数中最大的一个,S1的是4,小于指定的8。所以成员d就是按4字节对齐,c后补2个字节,后面是8个字节的结构体d。成员e是8个字节,它是默认按8字节对齐,和指定的一样,所以它对到8字节的边界上,这时,已经使用了12个字节了,所以d后又补上4个字节,从第16个字节开始放置成员e。这时,长度为24,已经可以被最大对齐参数8(成员e按8字节对齐)整除。这样,一共使用了24个字节。

   上面的不够复杂?再来一个:

    再看s2,c放在第一个字节。st1自己的对

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

  • 深入内存对齐的详解
  • 基于一个简单定长内存池的实现方法详解

相关文章

  • 2017-05-28构建mfc窗体的简单示例
  • 2017-05-28使用C语言详解霍夫曼树数据结构
  • 2017-05-28C语言循环队列的表示与实现实例详解
  • 2017-05-28C++读入XML文件示例
  • 2017-05-28.h和.cpp文件的区别(zt)详细介绍
  • 2017-05-28浅谈单调队列、单调栈
  • 2017-05-28浅谈C++中对象的复制与对象之间的相互赋值
  • 2017-05-28常用Hash算法(C语言的简单实现)
  • 2017-05-28关于C语言函数strstr()的分析以及实现
  • 2017-05-28C++如何动态的生成对象详解

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • C语言基础之malloc和free函数详解
    • 快速掌握VC6.0中各种宏注释应用(附图)
    • C++空类详解
    • 使用gcc在命令行中预定义宏
    • 深入解析C++中的字符数组和处理字符串的方法
    • C++中Cbitmap,HBitmap,Bitmap区别及联系
    • c语言读取obj文件转换数据的小例子
    • C++中I/O模型之select模型实例
    • 使用C++实现全排列算法的方法详解
    • 了解C++编程中指定的异常和未经处理的异常

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有