zoukankan      html  css  js  c++  java
  • #pragma pack(n)的含义及其用法

    Koder
            下面这篇文章详细介绍了关于内存处理中字节对齐。结构体 或者 类 存在字节对齐的问题,这个问题的理解需要对内存中数据的存放等有深刻的理解。是工程项目中经常需要用到的。
    ---------------------------------------------------------------------------------------------------

     #pragma pack(4)

      class TestB

      {

      public:

        int aa;

        char a;

        short b;

        char c;

      };

      int nSize = sizeof(TestB);

      这里nSize结果为12,在预料之中。

      现在去掉第一个成员变量为如下代码:

      #pragma pack(4)

      class TestC

      {

      public:

        char a;

        short b;

        char c;

      };

      int nSize = sizeof(TestC);

      按照正常的填充方式nSize的结果应该是8,为什么结果显示nSize为6呢?

    事实上,很多人对#pragma pack的理解是错误的。

    关于struct的使用方法

    struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对界(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同。

    自然对界是指按结构体的成员中 sizeof 最大的成员对齐。

    #pragma pack规定的对齐长度,实际使用的规则是:

    结构,联合,或者类的数据成员,第一个放在偏移为0的地方,以后每个数据成员的对齐,按照#pragma pack指定的数值和结构体的自然对齐长度中比较小的那个进行。
    就是说,当#pragma pack的值等于或超过所有数据成员长度的时候,这个值的大小将不产生任何效果。
    结构体的对齐,按照结构体中size最大的数据成员和#pragma pack指定值之间,较小的那个进行。

    具体解释:

    #pragma pack(4)

      class TestB

      {

      public:

        int aa; //第一个成员,放在[0,3]偏移的位置,

        char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。

        short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。

        char c; //第四个,自身长为1,放在[8]的位置。

      };

    这个类实际占据的内存空间是9字节

    类之间的对齐,是按照类内部最大的成员的长度,和#pragma pack规定的值之中较小的一个对齐的。

    所以这个例子中,类之间对齐的长度是min(sizeof(int),4),也就是4。

    9按照4字节圆整的结果是12,所以sizeof(TestB)是12。

    如果

    #pragma pack(2)

         class TestB

      {

      public:

        int aa; //第一个成员,放在[0,3]偏移的位置,

        char a; //第二个成员,自身长为1,#pragma pack(4),取小值,也就是1,所以这个成员按一字节对齐,放在偏移[4]的位置。

        short b; //第三个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[6,7]的位置。

        char c; //第四个,自身长为1,放在[8]的位置。

      };

    //可以看出,上面的位置完全没有变化,只是类之间改为按2字节对齐,9按2圆整的结果是10。

    //所以 sizeof(TestB)是10。

    最后看原贴:

    现在去掉第一个成员变量为如下代码:

      #pragma pack(4)

      class TestC

      {

      public:

        char a;//第一个成员,放在[0]偏移的位置,

        short b;//第二个成员,自身长2,#pragma pack(4),取2,按2字节对齐,所以放在偏移[2,3]的位置。

        char c;//第三个,自身长为1,放在[4]的位置。

      };

    //整个类的大小是5字节,按照min(sizeof(short),4)字节对齐,也就是2字节对齐,结果是6

    //所以sizeof(TestC)是6。

    在Linux下面就是

    #define __PACKED_ATTR        __attribute__ ((__packed__))
    typedef struct {

             char p[3] __PACKED_ATTR;

             long i __PACKED_ATTR;

    } test ;

    typedef struct {

             char p[3];

             long i;

    } test1;
    gcc test.c 编译后,它们的大小就是7,8了

    字节对齐可以用取余的方式来处理。

    例如#pragma pack(4) 如果结构体中有short 类型的数据 则去 min(sizeof(short), 4)为short的字节对齐边界。 sizeof(short) = 2; 所以存放该数据的内存的地方需要是 mem % 2 == 0 的地方。

    在做这些处理的时候, 可以画图的方式来看比较清晰。

    windows下面默认的是#pragma pack(8)
    所以如果要紧凑内存存放的话 需要用 #pragma pack(1)来限制了。

    因为编译器在编译时会对程序进行优化,以便加快访问速度,所以一般都会按照2的倍数进行字节对齐。用这个宏就是为了防止编译器对结构的定义进行对齐。

    #pragma(push,n)用来设置警告消息的等级 

  • 相关阅读:
    VIJOS1476 旅行规划(树形Dp + DFS暴力乱搞)
    神奇的图片
    How to locate elements/ Object locators for Android devices
    ZT: How to install appium with node.js
    How to get the appPackage and appActivity
    How to enable auto-complete for python in powershell
    Node.js
    Steps to develop an iterative algorithm
    Iterative Algorithm
    FSM
  • 原文地址:https://www.cnblogs.com/swordzj/p/2034739.html
Copyright © 2011-2022 走看看