​  C/C++编译器的缺省字节对齐方式为自然对界。即在缺省情况下,编译器为每一个变量或是数据单元按其自然对界条件分配空间。

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

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

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

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

1 struct Test
2 {
3 char x1; // 成员x1为char型(其起始地址必须1字节对界),其偏移地址为0
4 char x2; // 成员x2为char型(其起始地址必须1字节对界,其偏移地址为1
5 float x3; // 成员x3为float型(其起始地址必须4字节对界),编译器在x2和x3之间填充了两个空字节,其偏移地址为4
6 char x4; // 成员x4为char型(其起始地址必须1字节对界),其偏移地址为8
7 };

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

 1 #include <stdio.h>
2 typedef struct
3 {
4 int aa1; //4个字节对齐 1111
5 char bb1;//1个字节对齐 1
6 short cc1;//2个字节对齐 011
7 char dd1; //1个字节对齐 1
8 } testlength1;
9 int length1 = sizeof(testlength1); //4个字节对齐,占用字节1111 1011 1000,length = 12
10
11 typedef struct
12 {
13 char bb2;//1个字节对齐 1
14 int aa2; //4个字节对齐 01111
15 short cc2;//2个字节对齐 11
16 char dd2; //1个字节对齐 1
17 } testlength2;
18 int length2 = sizeof(testlength2); //4个字节对齐,占用字节1011 1111 1000,length = 12
19
20 typedef struct
21 {
22 char bb3; //1个字节对齐 1
23 char dd3; //1个字节对齐 1
24 int aa3; //4个字节对齐 001111
25 short cc23//2个字节对齐 11
26
27 } testlength3;
28 int length3 = sizeof(testlength3); //4个字节对齐,占用字节1100 1111 1100,length = 12
29
30 typedef struct
31 {
32 char bb4; //1个字节对齐 1
33 char dd4; //1个字节对齐 1
34 short cc4;//2个字节对齐 11
35 int aa4; //4个字节对齐 1111
36 } testlength4;
37 int length4 = sizeof(testlength4); //4个字节对齐,占用字节1111 1111,length = 8
38
39 int main(void)
40 {
41 printf("length1 = %d.\n",length1);
42 printf("length2 = %d.\n",length2);
43 printf("length3 = %d.\n",length3);
44 printf("length4 = %d.\n",length4);
45 return 0;
46 }

改变缺省的对界条件(指定对界)

· 使用伪指令#pragma pack (n),编译器将按照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指定的数值和子结构最大数据成员长度中,比较小的那个进行进行对齐。例子如下:

 1 #pragma pack(8)
2 struct s1
3 {
4 short a;
5 long b;
6 };
7
8 struct s2
9 {
10 char c;
11 s1 d;
12 long long e;
13 };
14 #pragma pack()

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

例子2按照2个字节对齐时:

 1 #include <stdio.h>
2 #pragma pack(2)
3 typedef struct
4 {
5 int aa1; //2个字节对齐 1111
6 char bb1;//1个字节对齐 1
7 short cc1;//2个字节对齐 011
8 char dd1; //1个字节对齐 1
9 } testlength1;
10 int length1 = sizeof(testlength1); //2个字节对齐,占用字节11 11 10 11 10,length = 10
11
12 typedef struct
13 {
14 char bb2;//1个字节对齐 1
15 int aa2; //2个字节对齐 01111
16 short cc2;//2个字节对齐 11
17 char dd2; //1个字节对齐 1
18 } testlength2;
19 int length2 = sizeof(testlength2); //2个字节对齐,占用字节10 11 11 11 10,length = 10
20
21 typedef struct
22 {
23 char bb3; //1个字节对齐 1
24 char dd3; //1个字节对齐 1
25 int aa3; //2个字节对齐 11 11
26 short cc23//2个字节对齐 11
27
28 } testlength3;
29 int length3 = sizeof(testlength3); //2个字节对齐,占用字节11 11 11 11,length = 8
30
31 typedef struct
32 {
33 char bb4; //1个字节对齐 1
34 char dd4; //1个字节对齐 1
35 short cc4;//2个字节对齐 11
36 int aa4; //2个字节对齐 11 11
37 } testlength4;
38 int length4 = sizeof(testlength4); //2个字节对齐,占用字节11 11 11 11,length = 8
39 #pragma pack()
40 int main(void)
41 {
42 printf("length1 = %d.\n",length1);
43 printf("length2 = %d.\n",length2);
44 printf("length3 = %d.\n",length3);
45 printf("length4 = %d.\n",length4);
46 return 0;
47 }

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

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

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

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


↓↓↓更多技术内容和书籍资料获取,入群技术交流敬请关注“明解嵌入式”↓↓↓

1分钟了解C语言正确使用字节对齐及#pragma pack的方法的更多相关文章

  1. 转载:C语言的字节对齐及#pragma pack的使用

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

  2. C语言中的字节对齐以及其相关处理

    首先,我们来了解下一些基本原理: 一.什么是字节对齐一个基本类型的变量在内存中占用n个字节,则该变量的起始地址必须能够被n整除,即: 存放起始地址 % n = 0,那么,就成该变量是字节对齐的;对于结 ...

  3. [置顶] 什么是C语言结构体字节对齐,为什么要对齐?

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

  4. C语言中的字节对齐

    下面这个篇博客讲解很好 http://blog.csdn.net/meegomeego/article/details/9393783 总的来看分三类: 1. 不加 #pragma pack(n)伪指 ...

  5. C语言:内存字节对齐详解[转载]

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

  6. c语言,内存字节对齐

    引用:内存字节对齐 写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的变量总长度要大,这是怎么回事呢?讲讲字节对齐吧. /************* ...

  7. C语言:内存字节对齐详解

    转:http://blog.csdn.net/arethe/article/details/2548867 一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论 ...

  8. C语言 结构体字节对齐问题

    摘选自这位大神的博客 方法一: 结构体在内存中分配一块连续的内存,但结构体内的变量并不一定是连续存放的,这涉及到内存对齐. 原则1  数据成员对齐规则:结构(struct或联合union)的数据成员, ...

  9. C语言 大小端 字节对齐

    参考:http://www.cnblogs.com/graphics/archive/2011/04/22/2010662.html 1. 大端序:数据的高位字节存放在地址的低端,低位字节存放在地址的 ...

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

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

随机推荐

  1. ORACLE ORA-12638:身份证明检索失败

    使用PLSQL连接远程数据库时,有时候会遇到提示ORA-12638:身份证明检索失败的问题,怎么办呢?有两种方法,选择一种更改就行了,网络上大多是第一种方法,如果已经找过不是你想要的答案,那不妨直接看 ...

  2. mysqld_safe Directory '/tmp/mysql' for UNIX socket file don't exists.

    报错版本:mysql-5.7.35 1.报错完整提示信息: [root@localhost bin]# 2022-11-15T04:04:43.122905Z mysqld_safe Logging ...

  3. SDN实验环境配置

  4. Springboot jar 打包脚本和启动脚本

    说明: SpringBoot极大的提高了工作效率,集成了各大厂优秀的组件,好处就不多说了,使用配置也非常方便,本文主要讲解如何使用更方便的方式打包发布,利用SpringBoot的新特性内置tomcat ...

  5. tableau连接mysql

    1.下载驱动地址:https://dev.mysql.com/downloads/connector/odbc/ 2.选择MSI Installer自动安装自动配置 3.本地127.0.0.1(其他I ...

  6. 不同时间格式转换问题_python2

    def unix_to_cst(data): """2019-03-17 11:00:00 --> Sun, 17 Mar 2019 11:00:00 GMT+08 ...

  7. 打不过AI就拉拢?ChatGPT和MidJourney已成我小秘书!

    为了体验AI,晓衡这两周战斗力爆棚了! 每天大概睡了四~五个小时,而且中午也没有休息过,但精神却还很亢奋. 直到周一下午,身体才有种被掏空的感觉,晚上 10 点就睡了.可能是兴奋劲还在,早晨不到 6 ...

  8. 通用图像分割任务- 使用 Mask2Former 和 OneFormer

    本文介绍两个领先的图像分割神经网络模型: Mask2Former 和 OneFormer.相关模型已经在 Transformers 提供. Transformers 是一个开源库,提供了很多便捷的先进 ...

  9. springboot脱包部署

    <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactI ...

  10. 【新版】使用 go-cqhttp 扫码登录,一键接入 ChatGPT 机器人到 QQ 群

    目录 项目效果 安装 go-cqhttp 虚拟文件 启动 ChatGPT 项目效果 由于 ChatGPT 目前只能在漂亮国使用,所以想要在国内使用 ChatGPT 必然险阻重重 不仅时时刻刻要跟企鹅公 ...