#Pragma Pack(n)与内存分配 pragma pack(push,1)与#pragma pack(1)的区别

from:http://blog.csdn.net/mylinx/article/details/7007309


 #pragma pack(n)

解释一:

每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。

  规则:

  1、数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

  2、结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

 

解释二:

n 字节的对齐方式 VC 对结构的存储的特殊处理确实提高 CPU 存储变量的速度,但是有时候也带来 了一些麻烦,我们也屏蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。 VC 中提供了#pragma pack(n)来设定变量以 n 字节对齐方式。n 字节对齐就是说 变量存放的起始地址的偏移量有两种情况:

第一、如果 n 大于等于该变量所占用的字 节数,那么偏移量必须满足默认的对齐方式。

第二、如果 n 小于该变量的类型所占用 的字节数,那么偏移量为 n 的倍数,不用满足默认的对齐方式。结构的总大小也有个 约束条件,分下面两种情况:如果 n 大于所有成员变量类型所占用的字节数,那么结 构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必须为 n 的倍数。

下面举例说明其用法。 #pragma pack(push) //保存对齐状态

 #pragma pack(4)//设定为 4 字节对齐

struct test { char m1; double m4; int m3; }; #pragma pack(pop)//恢复对齐状态 以上结构体的大小为 16:

下面分析其存储情况,首先为 m1 分配空间,其偏移量 为 0,满足我们自己设定的对齐方式(4 字节对齐),m1 大小为 1 个字节。接着开始 为 m4 分配空间,这时其偏移量为 1,需要补足 3 个字节,这样使偏移量满足为 n=4 的倍数(因为 sizeof(double)大于 4),m4 占用 8 个字节。接着为 m3 分配空间,这时 其偏移量为 12,满足为 4 的倍数,m3 占用 4 个字节。这时已经为所有成员变量分配 了空间,共分配了 16 个字节,满足为 n 的倍数。如果把上面的#pragma pack(4)改为 #pragma pack(8),那么我们可以得到结构的大小为 24。

 

大家看了这些文字描述头也一定会发麻吧,我坚持读完后,然后自己编写了一个程序:

#pragma pack(4)

struct node{

  int e;
  char f;
  short int a;
  char b;

};

struct node n;

printf("%d\n",sizeof(n));

我自己算的结果是16,结果实际结果是:

 

然后结构体内部数据成员变动一下位置:

 

#pragma pack(4)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

 

将对齐位数强制定位2

#pragma pack(2)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

 

将对齐位数强制定位1

#pragma pack(1)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

 

看着输出结果和文字描述有点晕,下面简单说一下俺的判定规则吧:

 

其实之所以有内存字节对齐机制,就是为了最大限度的减少内存读取次数。我们知道CPU读取速度比内存读取速度快至少一个数量级,所以为了节省运算花费时间,只能以牺牲空间来换取时间了。

下面举例说明如何最大限度的减少读取次数。

#pragma pack(1)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

这里强制按照1字节进行对齐,可以理解成所有的内容都是按照1字节进行读取(暂且这样理解,因为这样可以很好的理解内存对其机制),其他所有的数据成员都是1字节的整数倍,所以也就不用进行内存对其,各个成员在内存中就按照实际顺序进行排列,结构体实际长度为8

 

 

#pragma pack(2)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

这里强制按照2字节进行对齐。如果内存分布仍然是连续的话,那么int e就得三次才能读到CPU中,所以为了“讲究”int e的读取,所以在char f之后预留1BYTE,最后的char b也是如此,所以长度为10

 

#pragma pack(4)

struct node{

  char f;
  int e;
  short int a;
  char b;};

struct node n;

printf("%d\n",sizeof(n));

这里强制按照4字节进行对齐。所以char f后要预留3BYTE,而short int a 和 char b可以一次读取到CPU(按照4字节读取),所以长度为12

 

如果#pramga pack(n)中的n大于结构体成员中任何一个成员所占用的字节数,则该n值无效。编译器会选取结构体中最大数据成员的字节数为基准进行对其

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

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


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

#pragma pack (n)             作用:C编译器将按照n个字节对齐。
#pragma pack ()               作用:取消自定义字节对齐方式。


#pragma  pack (push,1)     作用:是指把原来对齐方式设置压栈,并设新的对齐方式设置为1个字节对齐

#pragma pack(pop)            作用:恢复对齐状态

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

如:

#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()


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/458512.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

ShowDoc的搭建

其实&#xff0c;官方文档也说的很清楚了。主要贴一下我遇见的问题。环境&#xff1a;LNMP&#xff08;LAMP没试过&#xff0c;有兴趣的同学可以试试&#xff0c;然后发出来&#xff09;PHP5.3以上版本、php-mbstring模块、php-pdo模块、mysql数据库克隆或者下载代码&#xff1…

BroadcastReceiver

本文介绍Broadcast Receiver&#xff0c;包括几部分内容&#xff1a;Broadcast Receiver概述及实例、自定义Broadcast Receiver、Broadcast Receiver的实现细节、生命周期等。 csdn貌似今天出问题了&#xff0c;无法上传图片。 资料来源&#xff1a;最牛网&#xff0c;《官方解…

MFC CPropertySheet 多页面切换 实例

为了能实现在同一个页面实现多个页面的切换效果。CPropertySheet要与CPropertyPage一起使用。 首先 新建一个MFC工程--MFC AppWizard(exe), 取名Pagesheet, 选择Dialog based, 然后Finish. 2. 在对话框资源中插入两个对话框IDD_DIALOG1、IDD_DIALOG2&#xff0c;作为…

动画类的层次结构

CASpringAnimation类是CAABasicAnimation的子类 CAPropertyAnimation &#xff1a;是CAAnimation的子类&#xff0c;它支持动画地显示图层的keyPath&#xff0c;一般不直接使用。 iOS9.0之后新增CASpringAnimation类&#xff0c;它实现弹簧效果的动画&#xff0c;是CABasicAnim…

[原]小命令大作用:modprobe

调整网络为绑定模式&#xff0c;但启动时候会报错&#xff0c;此时执行命令 modprobe bonding 可以解决问题。 之前在磁盘方面遇到问题也是通过modprobe命令解决的&#xff0c;又遇到这个命令&#xff0c;似曾相识。于是看下该命令&#xff1a; Linux命令&#xff1a;modprobe …

setup2go制作安装程序

QT程序设计完毕时&#xff0c;我们就要发布自己的程序&#xff0c;发布程序有两种方法&#xff1a;一是静态编译&#xff0c;二是制作程序安装包。 静态编译好麻烦&#xff0c;我从来没有成功过&#xff0c;所以我用了动态编译方法&#xff0c;设计完成时&#xff0c;用release…

数据结构比较型排序算法分析及选择

比较型算法分为五类&#xff1a; 1、插入排序&#xff1a;直接插入排序、折半插入排序、希尔排序&#xff1b; 2、选择排序&#xff1a;直接选择排序、堆排序&#xff1b; 3、交换排序&#xff1a;快速排序、冒泡排序&#xff1b; 4、归并排序&#xff1b; 5、基数排序&#xf…

Frequent Pattern 挖掘之二(FP Growth算法)(转)

FP树构造 FP Growth算法利用了巧妙的数据结构&#xff0c;大大降低了Aproir挖掘算法的代价&#xff0c;他不需要不断得生成候选项目队列和不断得扫描整个数据库进行比对。为了达到这样的效果&#xff0c;它采用了一种简洁的数据结构&#xff0c;叫做frequent-pattern tree(频繁…

Sublime 解决目录显示为方块的问题

2019独角兽企业重金招聘Python工程师标准>>> 修改Perferences->Settings-User { "font_face": "Consolas Italic", #传说这个字体比较好看。 "font_size": 15, "ignored_packages": [ "Vintage" ], "dpi…

VS toolTip1控件的使用1

http://blog.csdn.net/Mr_Liyong/article/details/780141381、在工具栏找到“toolTip”控件后拖到窗体后&#xff0c;窗体下方会显示此控件则拖放成功。 2、单击此控件右键选择属性&#xff1a;开始 修改属性。 3、当添加一个TOOLTIP控件后&#xff0c;在WINFORM界面上所有的控…

【TL】【编码】瞬间移动-百度之星初赛(Astar Round2B)1003-2016.05.22

瞬间移动 Accepts: 1018 Submissions: 3620Time Limit: 4000/2000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others) Problem Description有一个无限大的矩形&#xff0c;初始时你在左上角&#xff08;即第一行第一列&#xff09;&#xff0c;每次你都可以选择一个…

dom解析xml

为什么80%的码农都做不了架构师&#xff1f;>>> 转载自&#xff1a;http://www.cnblogs.com/shenliang123/archive/2012/05/11/2495252.html 使用eclipse需要手动导入crimson.jar包 org.w3c.dom(java dom)解析XML文档 位于org.w3c.dom操作XML会比较简单&#xff0c…

逃离北上广:你以为回到小城市就非常幸福了吗?

忘记在哪儿看的了。感觉不错&#xff0c;随手发出来。我博客也有更新&#xff0c;底下有留个人博客链接 在过去几年里。“逃离北上广”一直是一个热门短语。拿我自己来说&#xff0c;工作在上海&#xff0c;但又不是上海人。毕业后&#xff0c;就选择租房&#xff0c;首先就为这…

[WinForm] VS2010发布、打包安装程序(超全超详细)

from: http://blog.csdn.net/y13156556538/article/details/555321841、 在vs2010 选择“新建项目”→“ 其他项目类型”→“ Visual Studio Installer→“安装项目”&#xff1a; &#xff08;如果是在solution中添加&#xff0c;就直接solution -- 右键 -- 添加project&#…

【译】什么导致了Context泄露:Handler内部类

思考下面代码 1 public class SampleActivity extends Activity { 2 3 private final Handler mLeakyHandler new Handler() { 4 Override 5 public void handleMessage(Message msg) { 6 // ... 7 } 8 } 9 } 如果没有仔细观察&#xff0c;上面的代码…

苹果应用上架遇到的问题(2017年4月27日)

在更新app store的时候报&#xff08;如图&#xff09;&#xff1a; ERROR ITMS-90086: "Missing 64-bit support. iOS apps submitted to the App Store must include 64-bit support and be built with the iOS 8 SDK or later. We recommend using the default "S…

工作者对象HttpWorkerRequest

在ASP.NET中&#xff0c;用于处理的请求&#xff0c;需要封装为HttpWorkerRequest类型的对象。该类为抽象类&#xff0c;定义在命名空间System.Web下。 #region Assembly System.Web.dll, v4.0.0.0 // C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFr…

苹果应用上架,一些信息的勾选(2017年4月27日)

1、分级的各种选项的选择全部选否 &#xff08;我们公司是医疗相关的app&#xff0c;医疗的选项也是选择的否&#xff09; 2、

C# 线程池ThreadPool

什么是线程池&#xff1f;为什么要用线程池&#xff1f;怎么用线程池&#xff1f; 1. 什么是线程池&#xff1f;.NET Framework的ThreadPool类提供一个线程池&#xff0c;该线程池可用于执行任务、发送工作项、处理异步 I/O、代表其他线程等待以及处理计时器。那么什么是线程池…

苹果应用上架,图片的要求(2017年4月27日)

看这个提示应该就明白了吧。 哈哈&#xff0c;我还是自己再说一遍加深一下印象吧&#xff1a;如果应用在各个尺寸iphone屏幕上面外观一样&#xff0c;就只准备5.5英寸的图就可以了&#xff1b;如果有所不同&#xff0c;就按照实际情况&#xff0c;准备不同屏幕尺寸的图片即可。…