C语言的字节对齐及#pragma pack的使用

转载 2015年07月08日 15:05:13

来自http://www.cnblogs.com/dabiao/archive/2010/04/15/1712458.html

C编译器的缺省字节对齐方式(自然对界)


在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。

在结构中,编译器为结构的每个成员按其自然对界(alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储(成员之间可能有插入的空字节),第一个成员的地址和整个结构的地址相同。

 

C编译器缺省的结构成员自然对界条件为“N字节对齐”,N即该成员数据类型的长度。如int型成员的自然对界条件为4字节对齐,而double类型的结构成员的自然对界条件为8字节对齐。若该成员的起始偏移不位于该成员的“默认自然对界条件”上,则在前一个节面后面添加适当个数的空字节。

 

C编译器缺省的结构整体的自然对界条件为:该结构所有成员中要求的最大自然对界条件。若结构体各成员长度之和不为“结构整体自然对界条件的整数倍,则在最后一个成员后填充空字节。

例子1(分析结构各成员的默认字节对界条界条件和结构整体的默认字节对界条件):

复制代码
struct Test
{
char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0

char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1

float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4

char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8
};
复制代码


因为Test结构体中,最大的成员为flaot x3,因些此结构体的自然对界条件为4字节对齐。则结构体长度就为12字节,内存布局为1100 1111 1000。

例子2:

复制代码
#include <stdio.h>
//#pragma pack(2)
typedef struct
{
int aa1; //4个字节对齐 1111
char bb1;//1个字节对齐 1
short cc1;//2个字节对齐 011
char dd1; //1个字节对齐 1
} testlength1;
int length1 = sizeof(testlength1); //4个字节对齐,占用字节1111 1011 1000,length = 12

typedef
struct
{
char bb2;//1个字节对齐 1
int aa2; //4个字节对齐 01111
short cc2;//2个字节对齐 11
char dd2; //1个字节对齐 1
} testlength2;
int length2 = sizeof(testlength2); //4个字节对齐,占用字节1011 1111 1000,length = 12


typedef
struct
{
char bb3; //1个字节对齐 1
char dd3; //1个字节对齐 1
int aa3; //4个字节对齐 001111
short cc23//2个字节对齐 11

} testlength3;
int length3 = sizeof(testlength3); //4个字节对齐,占用字节1100 1111 1100,length = 12


typedef
struct
{
char bb4; //1个字节对齐 1
char dd4; //1个字节对齐 1
short cc4;//2个字节对齐 11
int aa4; //4个字节对齐 1111
} testlength4;
int length4 = sizeof(testlength4); //4个字节对齐,占用字节1111 1111,length = 8


int main(void)
{
printf(
"length1 = %d.\n",length1);
printf(
"length2 = %d.\n",length2);
printf(
"length3 = %d.\n",length3);
printf(
"length4 = %d.\n",length4);
return 0;
}
复制代码

改变缺省的对界条件(指定对界)
· 使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。
· 使用伪指令#pragma pack (),取消自定义字节对齐方式。


这时,对齐规则为:

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

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

结合1、2推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

 

因此,当使用伪指令#pragma pack (2)时,Test结构体的大小为8,内存布局为11 11 11 10。


需要注意一点,当结构体中包含一个子结构体时,子结构中的成员按照#pragma pack指定的数值和子结构最大数据成员长度中,比较小的那个进行进行对齐。例子如下:

#pragma pack(8)
struct s1{
short a;
long b;
};


struct s2{
char c;
s1 d;
long long e;
};
#pragma pack()

sizeof(s2)的结果为24。S1的内存布局为1100 1111,S2的内存布局为1000 1100 1111 0000 1111 1111。

例子:

复制代码
#include <stdio.h>
#pragma pack(2)
typedef
struct
{
int aa1; //2个字节对齐 1111
char bb1;//1个字节对齐 1
short cc1;//2个字节对齐 011
char dd1; //1个字节对齐 1
} testlength1;
int length1 = sizeof(testlength1); //2个字节对齐,占用字节11 11 10 11 10,length = 10

typedef
struct
{
char bb2;//1个字节对齐 1
int aa2; //2个字节对齐 01111
short cc2;//2个字节对齐 11
char dd2; //1个字节对齐 1
} testlength2;
int length2 = sizeof(testlength2); //2个字节对齐,占用字节10 11 11 11 10,length = 10


typedef
struct
{
char bb3; //1个字节对齐 1
char dd3; //1个字节对齐 1
int aa3; //2个字节对齐 11 11
short cc23//2个字节对齐 11

} testlength3;
int length3 = sizeof(testlength3); //2个字节对齐,占用字节11 11 11 11,length = 8


typedef
struct
{
char bb4; //1个字节对齐 1
char dd4; //1个字节对齐 1
short cc4;//2个字节对齐 11
int aa4; //2个字节对齐 11 11
} testlength4;
int length4 = sizeof(testlength4); //2个字节对齐,占用字节11 11 11 11,length = 8


int main(void)
{
printf(
"length1 = %d.\n",length1);
printf(
"length2 = %d.\n",length2);
printf(
"length3 = %d.\n",length3);
printf(
"length4 = %d.\n",length4);
return 0;
}
复制代码

另外,还有如下的一种方式:

· __attribute((aligned (n))),让所作用的结构成员对齐在n字节自然边界上。如果结构中有成员的长度大于n,则按照最大成员的长度来对齐。

· __attribute__ ((packed)),取消结构在编译过程中的优化对齐,按照实际占用字节数进行对齐。


以上的n = 1, 2, 4, 8, 16... 第一种方式较为常见。

C语言的字节对齐 #pragma pack(n)2

#pragma pack(n) 解释一: 每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n),n=1,2,4,8,16来改变这一系...
  • yusiguyuan
  • yusiguyuan
  • 2015年03月23日 15:10
  • 2050

结构体字节对齐,pragma pack,__attribute__(packed)

程序编译器对结构的存储的特殊处理确实提高CPU存储变量的速度,但是有时候也带来了一些麻烦,我们也屏   蔽掉变量默认的对齐方式,自己可以设定变量的对齐方式。 例如我们设置结构体的对齐方式: stru...
  • zhangxiong2532
  • zhangxiong2532
  • 2016年03月08日 14:46
  • 2201

XCode IOS使用#pragma pack(8)无效

http://hi.baidu.com/123_mu_tou_ren/item/55fa93034b95fd33a3332a24
  • brook0344
  • brook0344
  • 2014年05月27日 22:14
  • 2226

C语言之#pragma pack或者__packed学习

C语言之#pragma pack学习 转自:http://www.cppblog.com/range/archive/2011/07/15/151094.html #pragma pack学...
  • xlhcgd
  • xlhcgd
  • 2015年05月28日 11:47
  • 1199

pragma pack字节对齐详解

强调一点: #pragma pack(4) typedef struct {     char buf[3];     word a; }kk; #pragma pack() 对齐的原则是min(si...
  • yangyangye
  • yangyangye
  • 2014年12月24日 17:36
  • 1582

c语言之被遗漏的角落---#pragma pack

#PS:请尊重原创,不喜勿喷 #PS:要转载请注明出处,本人版权所有 #PS:这个只是  《  我自己    》理解,如果和你的原则相冲突,请 谅...
  • u011728480
  • u011728480
  • 2016年05月15日 17:21
  • 474

C语言的字节对齐及#pragma pack的使用

C语言的字节对齐及#pragma pack的使用 C编译器的缺省字节对齐方式(自然对界)在缺省情况下,C编译器为每一个变量或是数据单元按其自然对界条件分配空间。在结构中,编译器为结构的每个成员按其自然...
  • Augusdi
  • Augusdi
  • 2014年07月05日 11:43
  • 842

#program pack() 字节对齐

指令sidt读取IDT结构时,用到了#program pack(push,1)                                              #program(pop)学习...
  • hfdwdjl
  • hfdwdjl
  • 2012年10月29日 10:32
  • 2272

(C)字节对齐#pragma pack()

为什么要进行对齐对于结构体,编译器会自动进行成员变量对齐处理,是为了提高运算效率。 缺省情况下是自然对齐方式。自然对齐即默认对齐,按照结构体的成员中size最大的成员进行对齐。 例:struct ...
  • yang_hong_
  • yang_hong_
  • 2015年07月22日 12:48
  • 209

#pragma pack 更改字节对齐方式

#pragma pack 更改字节对齐方式
  • HuaHuaXia
  • HuaHuaXia
  • 2015年03月20日 18:35
  • 396
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:C语言的字节对齐及#pragma pack的使用
举报原因:
原因补充:

(最多只允许输入30个字)