zoukankan      html  css  js  c++  java
  • 【C++】字节对齐,也就是一个结构体的实际大小

    字节对齐是面试笔试经常考到的一个知识点

    计算一个结构体大小只需要进行如下几个步骤即可。

    1.确认结构体中所有成员的长度大小

      可以引用此表。

     

     

    char

    short

    int

    long

    float

    double

    long long

    long double

    Win-32

    长度

    1

    2

    4

    4

    4

    8

    8

    8

    模数

    1

    2

    4

    4

    4

    8

    8

    8

    Linux-32

    长度

    1

    2

    4

    4

    4

    8

    8

    12

    模数

    1

    2

    4

    4

    4

    4

    4

    4

    Linux-64

    长度

    1

    2

    4

    8

    4

    8

    8

    16

    2.确定系统默认的对齐模数:

      【#pragma pack指定的数值】、【未指定#pragma pack时,vc6 中默认是8

       在下面这种形式下就是自己指定对齐模数。

      #pragma pack(2)

      struct my_struct

      {

          char a;

          long double b;

      };

      #pragma pack()

     

    3.此时就会得到一组数和一个数(每个成员的大小 和 系统的模数) 按照以下方法计算即可得到总长度length=0

      1.拿出第一个成员的长度加到总长度里面  length += sizeof(member1) 因为对于第一个成员不存在对齐问题 都是从0开始

      2.拿出第二个成员的长度,和系统模数比较 拿出较小的数 min

      3.在前一个成员后面进行移动,让加上字节后的地址可以被 min整除,第二个成员的其实位置就是这个地址。 

      4.以此类推

    4.最后 拿出所有成员中最大的长度max 和系统模数比较,拿出较小的totalmin,看现在的总长度能不能被totalmin整除,如果可以现在就行了,如果不可以在后面加上n让总长度可以被totalmin整除  最后就是最终大小。

     

    举个例子:

      

    struct my_struct

    {

        char a;

        double b;

    };

      第一步:获得所有成员的长度:a 的长度是 1   b的长度是 8  

      第二步:获取系统的模数  此时没有指定pack 所以用vc6中默认的即可   8

      第三步:把a算进去 现在总长度是1了,内存布局为[0] 0位置存放的就是a  然后拿出b的长度8 和默认的8比较,取出较小的 也就是8, 此时b所在的位置应该能被8整除

          但是我们看 a是从0开始的 a的长度是1  所以 必须把地址向后移动7位,让b的起始地址是8 才能保证被8整除。所以在a和b之间要加入7个空位,然后让b从8开始

          [0][1 2 3 4 5 6 7] [8 9 10 11 12 13 14 15]

      第四部:总长度为 a + b + 空  =  1 + 8 + 7 = 16 

          拿出所有成员中最长的b 也就是8  拿出系统默认的8 取较小的8

          看16能否被8整除  这里可以,所以最后长度为16

     

    再来个复杂的:

      

    struct my_struct

    {

        int a;

        char b;

        double c;

        int d;

        char e;

    }; 

      还是按照那几步骤:

        1.获取所有成员的长度 分别是 4 1 8 4 1

        2.获取系统模数 这里没自定义pack 所以是 8

        3. 第一个成员a 从0位置开始 占据[0123] 四个字节  

          然后轮到b了。因为a占据0123了 所以b从4开始   b的长度是1 ,和系统模数8比,取出小的 1 。4可以被1整除,不用补空位   此时 [0123][4 ]    0123放着a   4放着b

            然后轮到c了,c是8 和系统模数比 取出小的 8  ,01234都有 东西了,c要从5开始,但是5不能被8整除 想要被8整除,最起码要在8这个位置开始 所以567存放空位,c从8开始 此时[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15]

          现在轮到d了, d是4  系统模式是8  拿出小的 4  起始地址16 能被4整除,所以d就从16开始[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19]

          最后轮到了e,  1和8比 拿出1  起始地址为20 能被1整除,所以最后结构是[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19][20]

        4.最后拿出所有成员中最长的 是c 长度为8  和系统模数8 比 取出小的   8

           现在的总长度21不能被8整除,所以仍然要向后补3位[0 1 2 3] [4] [5 6 7] [8 9 10 11 12 13 14 15][16 17 18 19][20][21 22 23] 

          一共24字节。

     

    注意:

      有指针成员,大小按照指针的大小即可。

    注意:关于64位系统和32位系统的大小

      可以确定的是32位系统的指针大小为32位 也就是4字节

      64位系统的指针大小为64位 就是8字节

      但是对于int型 long double 等类型,32位64位根据系统不同大小不同。没有确定标准

      但是如果出现int32_t 或者 int64_t ,这些是为了保证可移植性而定义的类型,表示32位的int和64位的int,长度分别为固定的32位和64位

  • 相关阅读:
    linux常用快捷键
    msf远程调用OpenVAS
    (三)漏洞平台搭建-xssplatform
    (二)漏洞平台搭建-sql-lab
    (一)漏洞平台搭建-DVWA
    msf永恒之蓝漏洞利用命令总结
    解决kali无法全屏问题
    centos7源码安装mysql数据库
    【多数人的误区】十二生肖属相不是从春节开始算的!
    python元组不可变是指什么不可变
  • 原文地址:https://www.cnblogs.com/heanqing/p/4908360.html
Copyright © 2011-2022 走看看