zoukankan      html  css  js  c++  java
  • (转载)关于#pragma pack(push,1)和#pragma pack(1)

    转载http://www.rosoo.net/a/201203/15889.html

    一、#pragma pack(push,1)与#pragma pack(1)的区别

    这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式。 

    #pragma  pack (n)                   作用:C编译器将按照n个字节对齐。
    #pragma  pack ()                     作用:取消自定义字节对齐方式。
    #pragma  pack (push,1)           作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为一个字节对齐
    #pragma  pack(pop)                 作用:恢复对齐状态

    因此可见,加入push和pop可以使对齐恢复到原来状态,而不是编译器默认,可以说后者更优,但是很多时候两者差别不大

    这是给编译器用的参数设置,有关结构体字节对齐方式的设置;大概是指把原来对齐方式设置压栈,并设新的设置为1

    比如我以此使用

    // test.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    
    
    #pragma  pack(push,1)
    
    #pragma  pack(push,8)
    
    
    
    typedef struct  ZT_MyStruct1
    {
        char a;
        double ab;
    } MyStruct1;
    
    
    #pragma  pack(pop)
    
    
    
    typedef struct  ZT_MyStruct2
    {
        char a;
        double ab;
    } MyStruct2;
    
    #pragma  pack(pop)
    #pragma  pack(pop)
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        MyStruct1 abc;
        MyStruct2 adb;
    
        printf("%d
    %d
    ",sizeof(abc),sizeof(adb));
        getchar();
        return 0;
    }
    //结果分别是16和9

    依次以按1和8字节入栈然后依次出栈8,1


    如:

    #pragma pack(push)   //保存对齐状态 
    #pragma pack(4)        //设定为4字节对齐 

    相当于 #pragma  pack (push,4) 


    #pragma  pack (1)           作用:调整结构体的边界对齐,让其以一个字节对齐;<使结构体按1字节方式对齐>
    #pragma  pack ()


    例如:

    #pragma pack(1) 
     
    struct sample 
    { 
      char a; 
      double b; 
    }; 
     
    #pragma pack() 

      注:若不用#pragma pack(1)和#pragma pack()括起来,则sample按编译器默认方式对齐(成员中size最大的那个)。即按8字节(double)对齐,则 sizeof(sample)==16.成员char a占了8个字节(其中7个是空字节);若用#pragma pack(1),则sample按1字节方式对齐sizeof(sample)==9.(无空字节),比较节省空间啦,有些场和还可使结构体更易于控制。

    应用实例
      在网络协议编程中,经常会处理不同协议的数据报文。一种方法是通过指针偏移的方法来得到各种信息,但这样做不仅编程复杂,而且一旦协议有变化,程序修改起来 也比较麻烦。在了解了编译器对结构空间的分配原则之后,我们完全可以利用这一特性定义自己的协议结构,通过访问结构的成员来获取各种信息。这样做,不仅简 化了编程,而且即使协议发生变化,我们也只需修改协议结构的定义即可,其它程序无需修改,省时省力。下面以TCP协议首部为例,说明如何定义协议结构。其 协议结构定义如下:

    #pragma pack(1) // 按照1字节方式进行对齐 
    struct TCPHEADER  
    { 
          short SrcPort; // 16位源端口号 
         short DstPort; // 16位目的端口号 
         int SerialNo; // 32位序列号 
         int AckNo; // 32位确认号 
         unsigned char HaderLen : 4; // 4位首部长度 
         unsigned char Reserved1 : 4; // 保留6位中的4位 
         unsigned char Reserved2 : 2; // 保留6位中的2位 
         unsigned char URG : 1; 
          unsigned char ACK : 1; 
          unsigned char PSH : 1; 
          unsigned char RST : 1; 
          unsigned char SYN : 1; 
          unsigned char FIN : 1; 
          short WindowSize; // 16位窗口大小 
         short TcpChkSum; // 16位TCP检验和 
         short UrgentPointer; // 16位紧急指针 
    };  
    #pragma pack() 

     例子一、

    // test.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    
    
    #ifdef WIN32
    //#ifdef WIN321
        #pragma  pack(push,1)
        #define PACKED  //define PACKED只是起标识作用并无实际意义
    #else
        #pragma  pack(push,4)
        #define PACKED 
    #endif
    
    
    typedef struct  ZT_MyStruct
    {
        char a;
        double ab;
    }PACKED MyStruct;
    
    int _tmain(int argc, _TCHAR* argv[])
    {
        MyStruct abc;
    
        printf("%d
    
    ",sizeof(abc));
        getchar();
        return 0;
    }
    
    /*
    1)直接运行程序结果为12
    2)改为#ifdef WIN321结果按一字节对齐为9
    */
  • 相关阅读:
    Power BI for Office 365(八)共享查询
    Power BI for Office 365(七) Power BI站点
    Power BI for Office 365(六)Power Map简介
    Power BI for Office 365(五)Power View第二部分
    Power BI for Office 365(四)Power View第一部分
    Power BI for Office 365(三)Power Pivot
    Power BI for Office 365(二)Power Query
    java 继承、重载、重写与多态
    Android 热修复方案Tinker(一) Application改造
    阿里最新热修复Sophix与QQ超级补丁和Tinker的实现与总结
  • 原文地址:https://www.cnblogs.com/ztteng/p/3419655.html
Copyright © 2011-2022 走看看