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

 

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;
}

改变缺省的对界条件(指定对界)
· 使用伪指令#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;
}

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

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

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

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

转载:C语言的字节对齐及#pragma pack的使用的更多相关文章

  1. 【C语言】字节对齐(内存对齐)

    数据对齐 1.  对齐原则: [原则1]数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照#pragma p ...

  2. C语言之字节对齐

    在C语言编程中,有时为了达到减少运行的时间的目的,需要浪费一些空间:而有时为了节省空间,使它的运行时间增长.而字节对齐则是为了访问效率,用空间换取时间. 要掌握字节对齐,首先得明确一下四个概念: 1. ...

  3. 【C语言】字节对齐问题(以32位系统为例)

    1. 什么是对齐? 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型 ...

  4. C语言学习 - 字节对齐

    字节对齐 字节对齐就是数据在内存中的位置. 假设一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐.比方在32位cpu下.假设一个整型变量的地址为0x00000004,那它就是自然对齐的. ...

  5. <摘录>字节对齐(强制对齐以及自然对齐)

    struct {}node; 32为的x86,window下VC下sizeof(node)的值为1,而linux的gcc下值为0: 一.WINDOWS下(VC--其实GCC和其原理基本一样,象这种问题 ...

  6. 字节对齐#pragma pack

    这是给编译器用的参数设置,有关结构体字节对齐方式设置, #pragma pack是指定数据在内存中的对齐方式. #pragma pack (n)             作用:C编译器将按照n个字节对 ...

  7. (转载)关于#pragma pack(push,1)和#pragma pack(1)

    转载http://www.rosoo.net/a/201203/15889.html 一.#pragma pack(push,1)与#pragma pack(1)的区别 这是给编译器用的参数设置,有关 ...

  8. C语言中内存对齐与结构体

    结构体 结构体是一种新的数据类型,对C语言的数据类型进行了极大的扩充. struct STU{ int age; char name[15]; }; struct STU a; //结构体实例 str ...

  9. c编译器字节对齐指令

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

随机推荐

  1. IN语句改写EXISTS

    -- IN SELECT T1.* FROM role_menu T1 WHERE T1.ROLEUUID IN ( SELECT T2.uuid FROM role T2 WHERE T2.UUID ...

  2. 以gnome-terminal为例,修改gnome3 的默认配置

    gnome连续几个版本的terminal默认配置文件都是同一个配置文件“b1dcc9dd-5262-4d8d-a863-c897e6d979b9”.这是因为gnome的developers编辑了这个配 ...

  3. ubuntu 安装codeblocks13.12

    通过添加PPA的方法安装: sudo add-apt-repository ppa:pasgui/ppa sudo apt-get update sudo apt-get install codebl ...

  4. 来说一说chrome扩展和chrome插件到底有什么区别?

    想讨论chrome扩展和chrome插件区别这个话题很久了!但是迟迟没有写.因为我自己也没有搞清楚这两者之间的区别!回想当初是因为需要寻找番羽墙插件才想到去搜索到chrome插件. 想讨论chrome ...

  5. (五)python3 整型int

    int() Python 内置函数,用于将一个字符串或数字转换为整型. int(x, base=10)#以十进制转换x为整型(默认) >>>int() # 不传入参数时,得到结果0 ...

  6. springcloud(十四):搭建Zuul微服务网关

    springcloud(十四):搭建Zuul微服务网关 1. 2. 3. 4.

  7. java8的LocalDateTime真心好用(补充Period.between的大坑)

    LocalDateTime.LocalDate是java8新增的时间工具类,最近使用后,真心觉得强大好用,推荐文章:https://www.liaoxuefeng.com/article/001419 ...

  8. 自定义Realm

    [单Realm] 1) jar包 2) 实现自定义Realm public class RealmOne implements Realm{ /** * 获取基本类名 */ @Override pub ...

  9. A+B Problem IV

    描述acmj最近发现在使用计算器计算高精度的大数加法时很不方便,于是他想着能不能写个程序把这个问题给解决了.   输入 包含多组测试数据每组数据包含两个正数A,B(可能为小数且位数不大于400) 输出 ...

  10. kuangbin专题最短路 D - Silver Cow Party

    #include<iostream> #include<cstring> #include<algorithm> #include<iomanip> # ...