历史上的今天
返回首页

历史上的今天

今天是:2025年02月05日(星期三)

正在发生

2021年02月05日 | STM32 字节对齐 #pragma pack

2021-02-05 来源:eefocus

1、对齐原则


min(sizeof(word ), 4) = 2,因此是 2 字节对齐,而不是我们认为的 4 字节对齐。


1)每个成员分别按自己的方式对齐,并能最小化长度;


2)复杂类型(如结构)的默认对齐方式是它最长的成员的对齐方式,这样在成员是复杂类型时,可以最小化长度;


3)对齐后的结构体整体长度必须是成员中最大的对齐参数的整数倍,这样在处理数组时可以保证每一项都边界对齐。


对于数组,比如 char a[3]:


它的对齐方式和分别写 3 个 char 是一样的,也就是说它还是按 1 个字节对齐;


如果是 typedef char Array3[3]:


Array3 这种类型的对齐方式还是按 1 个字节对齐,而不是按它的长度;


不论类型是什么,对齐的边界一定是 1,2,4,8,16,32,64.... 中的一个。


2、#pragma pack 作用


指定结构体、联合以及类成员的对齐 packing alignment;


3、语法


#pragma pack ( [show] | [push | pop] [, identifier], n )

说明:


1) pack 提供数据声明级别的控制,对定义不起作用;


2) 调用 pack 时不指定参数,n 将被设成默认值;


3) 一旦改变数据类型的 alignment,直接效果就是占用 memory 的减少,但是 performance 会下降;


语法具体分析:


1) show:可选参数


显示当前packing aligment的字节数,以warning message的形式被显示;


2) push:可选参数


将当前指定的packing alignment数值进行压栈操作,这里的栈是the internal compiler stack,同时设置当前的packing alignment为n;如果n没有指定,则将当前的packing alignment数值压栈;


3) pop:可选参数


从internal compiler stack中删除最顶端的record;如果没有指定n,则当前栈顶record即为新的packing alignment数值;


如果指定了n,则n将成为新的packing aligment数值;如果指定了identifier,则internal compiler stack中的record都将被pop直到identifier被找到,然后pop出identitier,同时设置packing alignment数值为当前栈顶的record;


如果指定的identifier并不存在于internal compiler stack,则pop操作被忽略;


4) identifier:可选参数


当同push一起使用时,赋予当前被压入栈中的record一个名称;


当同pop一起使用时,从internal compiler stack中pop出所有的record直到identifier被pop出,如果identifier没有被找到,则忽略pop操作;


5) n:可选参数


指定packing的数值,以字节为单位;


缺省数值是8,合法的数值分别是1、2、4、8、16。


取消字节对齐:


#pragma pack()    // 取消自定义字节对齐方式


4、重要规则


1)复杂类型中各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个类型的地址相同;


2)每个成员分别对齐,即每个成员按自己的方式对齐,并最小化长度;规则就是每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数中较小的一个对齐;


3)结构体、联合体或者类的数据成员,第一个放在偏移为0的地方;


以后每个数据成员的对齐,按照#pragma pack指定的数值和这个数据成员自身长度两个中比较小的那个进行;


也就是说,当#pragma pack指定的值等于或者超过所有数据成员长度的时候,这个指定值的大小将不产生任何效果;


4)复杂类型(如结构体)整体的对齐是按照结构体中长度最大的数据成员和#pragma pack指定值之间较小的那个值进行;


这样当数据成员为复杂类型(如结构体)时,可以最小化长度;


5)复杂类型(如结构体)整体长度的计算必须取所用过的所有对齐参数的整数倍,不够补空字节;


也就是取所用过的所有对齐参数中最大的那个值的整数倍,因为对齐参数都是2的n次方;这样在处理数组时可以保证每一项都边界对齐。


5、示例


强制对齐 #pragma pack:


#pragma pack(4)   // 按 4 字节对齐,但实际上由于结构体中单个成员的最大占用字节数为 2 字节,因此实际还是按 2 字节对齐

 

typedef struct

 

{

  // buf[1] 按 1 字节对齐,buf[2] 按 1 字节对齐,由于 buf[3] 的下一成员 word a 是按两字节对齐

  // 因此 buf[3] 按 1 字节对齐后,后面只需补一空字节

  char buf[3];

  

  // #pragma pack(4),取小值为 2,按 2 字节对齐

  word a;

} kk;

 


refer:


https://www.cnblogs.com/King-Gentleman/p/5297355.html


推荐阅读

史海拾趣

Connor-Winfield公司的发展小趣事

随着全球经济的一体化,电子行业也逐渐呈现出全球化的趋势。Connor-Winfield敏锐地把握住了这一机遇,开始实施全球化战略。公司积极拓展海外市场,与多家国际知名企业建立了紧密的合作伙伴关系。这些合作不仅为公司带来了更多的商业机会,也使其在全球化竞争中保持了领先地位。

Holmes Co Inc公司的发展小趣事

面对日益增长的全球市场需求,Holmes Electronics决定实施全球化战略。他们首先在亚洲建立了生产基地,利用当地的成本优势和供应链资源,大幅提高生产效率并降低成本。随后,公司又在欧洲和美国设立了研发中心和销售网络,以更好地服务当地客户并捕捉市场机会。这一全球化战略不仅使Holmes Electronics的产品遍布全球,还增强了公司的市场响应能力和品牌影响力。

Hexawave公司的发展小趣事

为了进一步提升竞争力,Holmes Electronics采取了一系列并购重组措施。他们首先收购了一家在物联网技术方面具有深厚积累的小型科技公司,通过整合双方资源,迅速在智能家居和智慧城市领域取得突破。随后,公司又成功并购了一家专业的半导体封装测试企业,进一步完善了产业链布局。这些并购重组不仅增强了Holmes Electronics的技术实力和市场地位,还为公司带来了新的增长动力。

C-MEDIA公司的发展小趣事

随着数字化时代的到来,C-MEDIA公司敏锐地捕捉到文化传媒市场的潜力。公司以法国主流电视台为传播平台,积极与中国主流媒体展开合作,成功开创了海外华人经营国际文化传媒的新模式。特别是在2014年,中国国务院新闻办独家授权C-MEDIA在欧洲播放中国影视数据库节目,这一举措极大地提升了公司在国际文化传媒领域的影响力。

固得沃克(GOODWORK)公司的发展小趣事

随着业务的不断拓展,固得沃克意识到技术升级和产能扩张的重要性。2019年,公司在江苏盐城成立了江苏固得沃克微电子科技有限公司,作为新的生产基地。该基地拥有2万平米的厂房,引进了具有国际水准的专业生产设备及先进检测仪器,并通过了ISO9001、ISO14001等国际管理体系认证。这一举措不仅提升了公司的生产能力和产品质量,还进一步巩固了其在半导体行业的地位。

HP(Keysight)公司的发展小趣事

随着业务的不断拓展,固得沃克意识到技术升级和产能扩张的重要性。2019年,公司在江苏盐城成立了江苏固得沃克微电子科技有限公司,作为新的生产基地。该基地拥有2万平米的厂房,引进了具有国际水准的专业生产设备及先进检测仪器,并通过了ISO9001、ISO14001等国际管理体系认证。这一举措不仅提升了公司的生产能力和产品质量,还进一步巩固了其在半导体行业的地位。

问答坊 | AI 解惑

arm_design(基于ARM的嵌入式系统(软件设计))

arm_design(基于ARM的嵌入式系统(软件设计))…

查看全部问答>

TMS320LF2407 DSP控制器的串行通信设计.doc

TI公司的TMS320LF2407型DSP微控制器内嵌的异步串行口(SCI)支持CPU与其它使用标准格式的异步外设之间的数字通讯,通过RS-232接口可以方便地进行DSP之间或与PC机之间的异步通信。而串行外设接口(SPI)是一个高速同步串行输入/输出(I/O)端口, ...…

查看全部问答>

BINFS mount不起来

先贴出一段我的debug模式下的打印信息 4294767296 PID:3829682 TID:382965a 0x83829470: FS: initializing ROM/RAM file system 4294767296 PID:3829682 TID:382965a 0x83829470: SC_CreateAPIHandle: pvData == NULL 4294767296 PID:3829682 TI ...…

查看全部问答>

如何直接写显卡内存达到显示图片的目的?

请问各位高人:如何直接对显卡显存来进行读写操作?由于我接收的是256*256的灰度数据,现在的处理方式是建立一个bmp文件,将数据填入进去,然后displaybmp,这样显得画面有些显示不及时,有覆盖或者错位的情况。后听人说起可以直接写显存,可是资料 ...…

查看全部问答>

用NiosII/e或NiosII/s ,系统正常运行;但换成NiosII/f ,系统不能正常运行,为什么?

有个FPGA的问题要请教,高手们帮忙看看呀,先谢谢了!        我使用DE0开发板,quartrsII 8.1 ,NiosII8.1 。在SOPC中组建的系统包括以下组件:NiosII,onchip_memory(设置为ram,30KB),lcd240128(自建液晶接口,set u ...…

查看全部问答>

Enet_tcp -客户端.

这是我根据网友academic以太网学习的例子改的,作为客户端链接主机的时候一直没有反应。请教大家问题出在哪里? #include #include \"inc/hw_ints.h\" #include \"inc/hw_memmap.h\" #include \"inc/hw_nvic.h\" #include \"inc/hw_types.h\" ...…

查看全部问答>

tiny6410置换2416开发板

tiny6410置换2416开发板 要求:开发资料详细。主要linux开发。 联系方式: qq:307799870…

查看全部问答>

100块活动审核通过名单好久公布

100块活动审核通过名单好久公布?…

查看全部问答>

基于互联网的远程智能家居控制系统设计

                                         智能热水器电路设计 核心处理器程序设计智能热水器 ...…

查看全部问答>