美文网首页
内存对齐详解

内存对齐详解

作者: 与时间共舞 | 来源:发表于2020-05-09 15:36 被阅读0次

1、什么是内存对齐
假设我们声明两个变量:

    char a; 
    short b;
    /**
    用 &(取地址符号)观察变量a,b的地址的话,我们会发现,如果a的地址是0x0000,那么b的地址符将会是0x0002或者是0x0004.那么就出现这样一个问题:0x0001这个地址没有被使用,那它干嘛去了呢?答案就是它 没有被使用。
因为CPU每次都是从以2字节(16位CPU)或是4字节(32位CPU)的整数倍的内存地址中读进数据的。如果变量b的地址是0x0001的话,那么CPU就需要先从0x0000中读取一个short,取它的高8位放入b的低8位,然后再从0x0002中读取下一个short,取它的低8位放入b的高8位中,这样的话,为了获得b的值,CPU需要进行了两次读操作。
    但是如果b的地址为0x0002,那么CPU只需一次读操作就可以获得b的值了。所以编译器为了优化代码,往往会根据变量的大小,将其指定到合适的位置,即称为内存对齐(对变量b做内存对齐,a、b之间的内存被浪费,a并未多占内存)。 
    */

2、结构体内存对齐规则

结构体所占用的内存与其成员在结构体中的声明顺序有关,其成员的内存对齐规则如下:

(1)每个成员分别按自己的对齐字节数和PPB(指定的对齐字节数,32位机默认为4)两个字节数最小的那个对齐,这样可以最小化长度。

(2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度。

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

(4)计算结构体的内存大小时,应该列出每个成员的偏移地址,则其长度=最后一个成员的偏移地址+最后一个成员数的长度+最后一个成员的调整参数(考虑PPB)。

3、案例讲解:

#pragma pack(2) //指定PPB为2
struct T{
char a; //偏移地址0
int b; //偏移地址2
char c; //偏移地址6
};

#pragma pack() //恢复原来默认PPB,32位下为4

int main(int argc,char * argv[])
{
printf("sizeof(struct T));
return 0;
}

————————————————
最后输出的结果为:8

#pragma pack(2)的作用是指定结构体按2字节对齐,即PPB=2。
分析:
变量a默认为1字节,PB=2,所以a按1字节对齐,a的偏移量为0;
变量b默认为4字节,PB=2,所以b按2字节对齐,b的偏移地址为2;
变量c默认为1字节,PB=2,所以按1字节对齐,偏移地址为6;
此时:结构体的计算出来的字节数为7个字节。最后按照规则,结构体对齐后的字节数为6(最后一个的偏移地址)+1(最后一个变量的字节长度)+1(补差)
案例1:
struct stu{ //指定PPB=2
    char a; //偏移地址0 
    char b; //偏移地址1 
    int c;  //偏移地址2 
}; 
//sizeof(stu)=2(最后一个成员的偏移地址)+4(最后一个成员数的长度)+2(补差)
//补差:最终求得长度要是结构体中最大数据类型的倍数 

案例2:
struct stu{ //指定PPB=4 
    char a; //偏移地址0 
    char b; //偏移地址1 
    int c;  //偏移地址4 
}; 
//sizeof(stu)=4(最后一个成员的偏移地址)+4(最后一个成员数的长度)=8 
struct stu1{ //指定PPB=4 
    char a; //偏移地址0 
    int b; //偏移地址4 
    char c;  //偏移地址8 
}; 
//sizeof(stu1)=8(最后一个成员的偏移地址)+1(最后一个成员数的长度)+3(补差)=12 

案例3:
//PPB:指定的对齐字节数,默认为 4(32位机),2(16位机) 
struct stu{   //PPB = 4
    char s[21];   //0   -- 偏移量(相对于结构体首地址) 
    double b;   //24
    float c;    //32 
    short d;    //36
};
//sizeof(stu) = 36+2+2=40 

4、注意的问题
(1)字节对齐取决于编译器;
(2)一定要注意PPB大小,PPB大小由pragam pack(n)指定;
(3)结构体占用的字节数要能够被PPB整除。
(4)总结出一个公式:结构体的大小等于最后一个成员的偏移量加上其大小再加上末尾的填充字节数目,即:
sizeof( struct ) = offsetof( last item ) + sizeof( last item ) +sizeof( trailing padding )

————————————————
原文链接:https://blog.csdn.net/SzMinglove/java/article/details/8143056

相关文章

  • sizeof与字节对齐

    参考 【面试题】sizeof引发的血案编译器与字节对齐c 语言字节对齐问题详解C/C++内存对齐内存存取粒度C和C...

  • 内存对齐详解

    1、什么是内存对齐假设我们声明两个变量: 2、结构体内存对齐规则 结构体所占用的内存与其成员在结构体中的声明顺序有...

  • C面试-内存对齐

    参考: 【嵌入式时代】C语言面试题详解(第7节),不知道“内存对齐”的程序员是不合格的 转载自:C语言的内存对齐 ...

  • 2.iOS底层学习之内存对齐

    学习了内存对齐之后的疑问?? 1.为啥要内存对齐?2.内存对齐的规则?3.内存对齐实例分析。 内存对齐的目的 上网...

  • 内存对齐

    本次主要讨论三个问题: 什么是内存对齐 内存对齐的好处 如何对齐 内存对齐 内存对齐是一种提高内存访问速度的策略。...

  • 结构体内存对齐

    对象内存对齐 探讨的问题 1.什么是内存对齐?2.为什么要做内存对齐?3.结构体内存对齐规则4.源码内存对齐算法 ...

  • Go语言内存对齐详解

    你必须非常努力,才能看起来毫不费力!微信搜索公众号[ 漫漫Coding路 ],一起From Zero To Her...

  • C 结构体对齐

    转载 结构体对齐详解 结构体数据成员对齐的意义 许多实际的计算机系统对基本类型数据在内存中存放的位置有限制,它们会...

  • 内存对齐

    内存对齐 什么叫内存对齐内存对齐就是按照特定的规则对数据进行存储,一般编译器按照8字节对齐标准处理。内存对齐一般用...

  • iOS内存对齐

    这篇文章我们来探索一下iOS内存对齐的原理,在探索完内存对齐原理之后,你就会明白内存对齐的好处。 在讲述内存对齐时...

网友评论

      本文标题:内存对齐详解

      本文链接:https://www.haomeiwen.com/subject/nsuknhtx.html