1分钟了解C语言正确使用字节对齐及#pragma pack的方法

这篇具有很好参考价值的文章主要介绍了1分钟了解C语言正确使用字节对齐及#pragma pack的方法。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

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

1分钟了解C语言正确使用字节对齐及#pragma pack的方法

        在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 }
1分钟了解C语言正确使用字节对齐及#pragma pack的方法

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

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

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

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


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

1分钟了解C语言正确使用字节对齐及#pragma pack的方法

 文章来源地址https://www.toymoban.com/news/detail-434401.html

到了这里,关于1分钟了解C语言正确使用字节对齐及#pragma pack的方法的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 大小端与字节对齐使用记录

    串口数据包解析 接收到的数据包: 其中数据内容为: 我们设计的结构体 使用内容复制函数 想要的数据: 实际的数据: 解决方法: CMSIS都已经给你写好的,请看core_cm3.h 执行完这个代码后 我们希望 实际上 解决方法:

    2024年02月07日
    浏览(26)
  • 深入了解C语言中的结构体类型与内存对齐

    在C语言中,结构体是一种 自定义的数据类型 , 它允许我们将不同类型的数据组合在一起,形成一个新的数据类型 。结构体的使用为我们解决了一些复杂数据的表示和处理问题,不仅限于单单的整型或者字符。本文将深入探讨结构体类型、结构体变量的创建和初始化,并详

    2024年04月11日
    浏览(32)
  • 10分钟了解人工智能(最通俗的语言)

    最通俗的语言:15分钟了解人工智能; 唯一优点,受众完全听懂 无人驾驶、智能家居、远程医疗 …… 如今,人工智能 (AI) 技术已被广泛应用于金融、交通、医疗、安防、教育等领域,成为经济增长新动能 一 什么是人工智能 人工智能,英文缩写为 AI ,指由人类制造出来的机

    2023年04月22日
    浏览(31)
  • 着色器GLSL ES语言10分钟了解

    参考资料:threejs中文网 threejs qq交流群:814702116 学习原生WebGL,除了前面说的JavaScript语言之外,你还需要学习一门新的语言就是着色器语言GLSL ES。 平时你接触的JavaScript、C、java等语言是在CPU上执行,对于着色器语言GLSL ES是在显卡GPU上执行。 如何学习 着色器语言GLSL ES语法虽

    2024年02月03日
    浏览(30)
  • 1分钟带你了解golang(go语言)

    Golang:也被称为Go语言,是一种开源的编程语言。由Google的Robert Griesemer、Rob Pike和Ken Thompson于2007年开始设计,2009年11月正式对外发布。(被誉为21世纪的C语言) 像python一样的优雅,有c一样的性能 天生的协程 编译快 … 编辑器: goland(推荐) 下载链接 vscode 官网:golang.goog

    2024年02月03日
    浏览(31)
  • 1分钟了解音频、语音数据和自然语言处理的关系

    音频、语音数据和自然语言处理这三者正在不断促进人工智能技术的发展,人机交互也逐渐渗透进生活的每个角落。在各行各业包括零售业、银行、食品配送服务商)的多样互动中,我们都能通过与某种形式的AI(如聊天机器人或虚拟助手)沟通来实现某些交易活动。语言是

    2024年02月09日
    浏览(34)
  • 2022-03-31 Amr-nb格式字节对齐、非字节对齐的转换和解码处理(含源码)

    AMR的格式分为AMR-NB、AMR-WB、AMR-WB+ 三种格式的区分和差异可以自行百度,在这里就不做细分了。 我相信,找到这篇文章的基本已经是入门了。 这一次我们主要处理的是AMR-NB格式的数据。本文主要贴出了如何区分字节对齐、非字节对齐的方法,以及如何处理解码?( 需要完整

    2024年02月02日
    浏览(22)
  • 位域和字节对齐

    位域是一种特殊的结构体成员,它允许将一个字节或多个字节中的每个位作为一个独立的成员来使用。位域的语法形式为: ``` ``` 其中,type 表示位域成员的类型,可以是 int、unsigned int、signed int 或者 char。member_name 表示位域成员的名称,可以省略。width 表示位域成员所占用的

    2024年02月05日
    浏览(25)
  • 【Golang】三分钟让你快速了解Go语言&为什么我们需要Go语言?

    博主简介: 努力学习的大一在校计算机专业学生,热爱学习和创作。目前在学习和分享:数据结构、Go,Java等相关知识。 博主主页: @是瑶瑶子啦 所属专栏: Go语言核心编程 近期目标: 写好专栏的每一篇文章 Go 语言从 2009 年 9 月 21 日开始作为谷歌公司 20% 兼职项目,即相关

    2023年04月21日
    浏览(46)
  • CAP结构体之字节对齐

    🍅 我是 蚂蚁小兵 ,专注于车载诊断领域,尤其擅长于对CANoe工具的使用 🍅 寻找组织 ,答疑解惑,摸鱼聊天,博客源码,点击加入👉【相亲相爱一家人】 🍅 玩转CANoe,博客目录大全,点击跳转👉 CAPL为什么也要理解字节对齐呢? 一般情况下,我们在定义/使用结构体的情

    2024年02月12日
    浏览(30)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包