历史上的今天
返回首页

历史上的今天

今天是:2025年04月01日(星期二)

正在发生

2019年04月01日 | STM32 字节对齐 #pragma pack

2019-04-01 来源: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;

 

推荐阅读

史海拾趣

Cal Crystal Lab Inc / Comclok Inc公司的发展小趣事

随着全球化的加速推进,国际化战略成为了企业发展的重要方向。Cal Crystal Lab Inc在稳固国内市场的基础上,积极实施国际化战略。公司不仅在海外设立了研发中心和生产基地,还加大了对国际市场的开拓力度。通过与当地企业的合作与交流,Cal Crystal Lab Inc不断适应国际市场的需求和变化,提升了公司在全球市场的竞争力。

这五个故事只是虚构的示例,并不代表任何真实公司的历史。实际的电子行业公司发展历程往往更加复杂和多样,受到市场、技术、政策等多种因素的影响。如果您需要了解特定公司的真实发展故事,建议查阅相关资料或咨询相关人士。

Axiohm公司的发展小趣事

Axiohm公司始终将社会责任作为企业发展的重要组成部分。公司积极参与社会公益事业,捐款捐物支持教育、扶贫等慈善项目。同时,Axiohm还注重员工福利和企业文化建设,为员工提供良好的工作环境和发展空间。这些举措不仅提升了公司的社会形象,也增强了员工的归属感和凝聚力。


这些故事虽然基于虚构,但反映了电子行业公司可能经历的一些典型发展历程和策略。请注意,这些故事并不代表Axiohm公司的实际情况,如需了解该公司的发展故事,建议查阅相关新闻报道或公司官方资料。

Aavid Niagra公司的发展小趣事

在快速发展的同时,Aavid Niagra公司始终关注企业社会责任和可持续发展。公司积极参与环保事业,推广绿色生产和消费理念。同时,公司还注重员工培训和福利保障,为员工创造一个良好的工作环境和发展空间。这些举措不仅提升了公司的社会形象,也为公司的长远发展奠定了坚实的基础。


这些故事框架主要围绕公司的初创、技术创新、全球化战略、行业变革应对以及企业社会责任等关键节点进行构建。您可以根据Aavid Niagra公司的实际情况和公开资料,对每个故事进行具体化和个性化的描述,以确保故事的准确性和可信度。

Alpha Semiconductor公司的发展小趣事

Alpha Semiconductor位于美国加州硅谷的研发与生产基地是公司发展的重要支撑。在这里,公司拥有一流的研发团队和先进的生产设备,能够为客户提供高质量的产品和服务。硅谷作为全球科技创新的中心之一,为Alpha Semiconductor提供了丰富的技术资源和人才支持,使得公司能够不断推陈出新,保持在半导体行业的领先地位。

通过以上五个故事,我们可以看到Alpha Semiconductor公司在电子行业中的发展历程。从初创时期的代工服务起步,到后来的OEM定制产品、自主研发电源管理产品,再到高性能标准模拟和混合信号IC的制造实力,以及在美国硅谷的研发与生产基地的建立,每一个阶段都见证了公司的成长和进步。Alpha Semiconductor凭借着不断的技术创新和市场拓展,已经成为了半导体行业中的佼佼者。

Bomar Interconnect公司的发展小趣事

在电子行业的激烈竞争中,Bomar Interconnect公司凭借持续的技术创新,逐渐崭露头角。公司研发团队不断深入研究新型连接技术,成功推出了一系列高性能、高可靠性的连接器产品。这些产品在市场上获得了广泛认可,为公司带来了稳定的收入来源。同时,公司还积极投入资源,加强与其他企业的技术合作,不断拓宽产品应用领域,进一步提升了公司的市场竞争力。

ET Enterprises Ltd公司的发展小趣事

近年来,ET Enterprises Ltd公司经历了一系列的收购和战略合作。这些举措不仅进一步增强了公司的实力和市场地位,也为公司的未来发展注入了新的活力。例如,公司成为得克萨斯州Ludlum Measurements Inc.的子公司后,受益于美国光电倍增管生产商ADIT的生产设施和ET Enterprises的开发设施的综合资源,为公司的持续发展提供了有力支持。

以上五个故事概述了ET Enterprises Ltd公司的发展历程和关键阶段,展示了公司在电子行业中不断崛起和持续发展的过程。

问答坊 | AI 解惑

LCD黑屏问题调试[PXA310 bootloader]

LCD黑屏问题调试[PXA310 bootloader] 1. PXA310+DA9034+NXP5209架构的手机 2.Bug:LCD黑屏问题调试 3.任务级别:bootloader XXX:为保密公司做的项目 附件功能用不了,我用latex写的报告, 1.复制粘贴至另一个文件后,保存为一个文件,文 ...…

查看全部问答>

基于nRF2401的无线信息发布平台

本帖最后由 paulhyde 于 2014-9-15 09:20 编辑 基于nRF2401的无线信息发布平台  …

查看全部问答>

怎样把电脑上的文件传到arm里边的linux去?

请教一下,arm下linux正在运行,通过串口连接到电脑上,怎样把电脑上的文件传到arm里边的linux去?或者给个关键词我百度一下~…

查看全部问答>

电子工程师,请不要为这五类人打工!

当初选择做技术,最主要的原因,是出于对科学技术的纯洁性的热爱,对人情世故的厌恶。但专于技术的工程师,要想有份有前途的工作,找到可以长久做下去的公司。“良禽择木而栖,贤臣择主而侍”,遇到下面五类性格的老板,能走多远就走多远。在此罗列 ...…

查看全部问答>

C51 的一个问题

我碰到一个C51的问题 执行如下语句时: unsigned int xdata w; for(w=0;w…

查看全部问答>

没天理了!STM32的定时器怎么这样啊?

想用TIM的外部时钟模式1的下做脉冲计数,可是仔细看了触发源很郁闷TS[2:0]:触发选择这3位选择用于同步计数器的触发输入。000:内部触发器0(ITR0),TIM1 001:内部触发器0(ITR1),TIM2 010:内部触发器0(ITR1),TIM3 011:内部 ...…

查看全部问答>

请香主和大侠看下RTC的问题(用官方库)已解决

先贴上中断部分的程序:void RTC_IRQHandler(void){  vu32 Time_temp;  if (RTC_GetITStatus(RTC_IT_SEC) != RESET)  {    /* Clear the RTC&nbs ...…

查看全部问答>

用Flash保存设置的数据,如何知道未用Flash

小弟用STM32做一光源控制器,其中一些相关的设置,希望能保存到Flash中,在下次开机的时候能够直接读取出来,省去重新设置的麻烦。 在保存数据的时候,我如何确定要保存到Flash的哪个地址?哪些地址是没有被代码使用到的? 代码是如何被存放 ...…

查看全部问答>