当前位置:首页 > 嵌入式 > 嵌入式教程
[导读]ARM C编译器支持基本的数据类型:char、short、int、long long、float和double。表14.2说明了armcc对C语言所使用的数据类型的映射。

14.8变量类型

ARMC编译器支持基本的数据类型:char、short、int、longlong、float和double。表14.2说明了armcc对C语言所使用的数据类型的映射。

表14.2 C编译器数据类型映射

C数据类型

表示的意义

char

无符号8位字节数据

short

有符号16位半字数据

int

有符号32位字数据

long

有符号32位字数据

longlong

有符号64位双字数据

ARM指令集中,无论是数据处理指令还是数据加载/存储指令,处理的数据类型不同,指令的执行效率是不一样的。本章将详细讨论,如何在程序中为变量分配合理的数据类型,来提高代码的执行效率。

14.8.1局部变量

ARM属于RISC的体系结构,所有大多数的数据处理都是在32位的寄存器中进行的。基于这个原因,局部变量应尽可能使用32位数据类型int或long。

注意

一些情况下不得不使用char或short类型,例如要使用char或short类型的数据溢出指令时归零特性时,如模运算255+1=0,就要使用char类型。

为了说明局部变量类型的影响,先来看一个简单的例子。

charcharinc(chara)

{

returna+1;

}

编译出的结果如下。

charinc

ADDa1,a1,#1

ANDa1,a1,#&ff

MOVpc,lr

再把上面的程序段中变量a声明位int型,代码如下。

intwordinc(inta)

{

returna+1;

}

比较一下编译器输出结果。

wordinc

ADDa1,a1,#1

MOVpc,lr

分析上面的两段代码不难发现,当把变量声明为char型时,编译器增加了额外的ADD指令来保证其范围在0~255之间。

14.8.2有符号数和无符号数

上一节讨论了对于局部变量和函数参数,使用int型比使用char或short型要好。本节将对程序中的有符号整数(signedint)和无符号整数(unsignedint)的执行效率进行分析比较。

首先来看上一节的例子,如果将变量指定为有符号的半字类型(编译器默认short型为有符号类型),程序的源代码如下。

shortshortinc(shorta)

{

returna+1;

}

编译后的结果如下。

shortinc

ADDa1,a1,#1

MOVa1,a1,LSL#16

MOVa1,a1,ASR#16

MOVpc,lr

分析发现,该结果比使用int型的变量多增加了两条指令(LSL和ASR)。编译器先将变量左移16位,然后右移16位,以实现一个16位符号扩展。右移是符号位扩展移位,它复制了符号位来填充高16位。

通常情况下,如果程序中只有加法、减法和乘法,那么有符号和无符号数的执行效率相差不大。但是,如果有了除法,情况就不一样了。详细内容可参加除法运算优化一节。

14.8.3全局变量1.边界对齐

对于RISC体系结构的处理器来说,访问边界对齐的数据要比访问非对齐的数据更高效。表14.3显示了ARM结构下各数据类型所占的字节数。

表14.3 各数据类型所占字节数

C数据类型

所占字节数

char,singedchar,unsignedchar

1

short,unsignedshort

2

int,unsignedint,long,unsignedlong

4

float

4

double

4

longlong

4

变量定义虽然很简单,但是也有很多值得注意的地方。先看下面的例子。

定义1:

chara;

shortb;

charc;

intd;

定义2:

chara;

charc;

shortb;

intd;

这里定义的4个变量形式都一样,只是次序不同,却导致了在最终映像中不同的数据布局,如同14.1所示,其中pad为无意义的填充数据。

图14.1变量在数据区里的布局

从图中可以看出,第二种方式节约了更多的存储器空间。

由此可见,在变量声明的时候需要考虑怎样最佳的控制存储器布局。当然,编译器在一定程度上能够优化这类问题,但最好的方法还是在编译的时候把所有相同类型的变量放在一起定义。

2.访问外部变量

首先来看一个例子。下面的例子定义了一些全局变量,在main()中为这些变量赋值并将其打印输出。

/************

*access.c*

************/

#include<stdio.h>

chartx;

charrx;

charbyte;

charc;

unsignedstate;

unsignedflags;

intmain()

{tx=1;

rx=2;

byte=3;

c=4;

state=5;

flags=6;

printf("%u%u%u%u%u%un",tx,rx,byte,c,state,flags);

return0;

}

使用armcc编译,生成的代码大小如下。

C$$code132

C$$data12

如果将全局变量声明为extern,变量的定义在其他文件中,那么生成的代码量将有所增加。

将全局变量声明为extern,生成的代码大小如下。

C$$code168

C$$data12

这是因为当将变量声明为extern后,每次访问变量编译器都将从内存重新加载,而不是使用内存偏移,直接访问。

下图显示编译器对声明为extern变量的访问。

解决的办法是将要从外部引用的extern变量定义在一个结构体中。在程序中通过结构体访问外部变量。具体用法如下例所示。

/*************

*globals.h*

*************/

/*DECLARATIONSofglobals-includedinallsources*/

#ifdef__arm

structglobs

{chartx;

charrx;

图14.2对extern变量的访问

charbyte;

charc;

unsignedstate;

unsignedflags;

};

externstructglobsg;

#definetxg.tx

#definerxg.rx

#definebyteg.byte

#definecg.c

#definestateg.state

#defineflagsg.flags

#else

externchartx;

externcharrx;

externcharbyte;

externcharc;

externunsignedstate;

externunsignedflags;

#endif

/*************

*globals.c*

*************/

/*DEFINITIONSofglobals-singlesourcefile*/

#ifdef__arm

#include"globals.h"

structglobsg;

#else

chartx;

charrx;

charbyte;

charc;

unsignedstate;

unsignedflags;

#endif

/************

*access.c*

************/

#include<stdio.h>

#include"globals.h"

intmain()

{tx=1;

rx=2;

byte=3;

c=4;

state=5;

flags=6;

printf("%u%u%u%u%u%un",tx,rx,byte,c,state,flags);

return0;

}

将变量定义在结构体内有以下几点好处。

·全局变量使用更小的内存空间。(没有使用结构体占有24字节,而使用结构体之后只占有12字节)

·全局变量被放置在ZI段而不是RW段,这样就减少了ROM映像文件的大小。

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: 驱动电源

在工业自动化蓬勃发展的当下,工业电机作为核心动力设备,其驱动电源的性能直接关系到整个系统的稳定性和可靠性。其中,反电动势抑制与过流保护是驱动电源设计中至关重要的两个环节,集成化方案的设计成为提升电机驱动性能的关键。

关键字: 工业电机 驱动电源

LED 驱动电源作为 LED 照明系统的 “心脏”,其稳定性直接决定了整个照明设备的使用寿命。然而,在实际应用中,LED 驱动电源易损坏的问题却十分常见,不仅增加了维护成本,还影响了用户体验。要解决这一问题,需从设计、生...

关键字: 驱动电源 照明系统 散热

根据LED驱动电源的公式,电感内电流波动大小和电感值成反比,输出纹波和输出电容值成反比。所以加大电感值和输出电容值可以减小纹波。

关键字: LED 设计 驱动电源

电动汽车(EV)作为新能源汽车的重要代表,正逐渐成为全球汽车产业的重要发展方向。电动汽车的核心技术之一是电机驱动控制系统,而绝缘栅双极型晶体管(IGBT)作为电机驱动系统中的关键元件,其性能直接影响到电动汽车的动力性能和...

关键字: 电动汽车 新能源 驱动电源

在现代城市建设中,街道及停车场照明作为基础设施的重要组成部分,其质量和效率直接关系到城市的公共安全、居民生活质量和能源利用效率。随着科技的进步,高亮度白光发光二极管(LED)因其独特的优势逐渐取代传统光源,成为大功率区域...

关键字: 发光二极管 驱动电源 LED

LED通用照明设计工程师会遇到许多挑战,如功率密度、功率因数校正(PFC)、空间受限和可靠性等。

关键字: LED 驱动电源 功率因数校正

在LED照明技术日益普及的今天,LED驱动电源的电磁干扰(EMI)问题成为了一个不可忽视的挑战。电磁干扰不仅会影响LED灯具的正常工作,还可能对周围电子设备造成不利影响,甚至引发系统故障。因此,采取有效的硬件措施来解决L...

关键字: LED照明技术 电磁干扰 驱动电源

开关电源具有效率高的特性,而且开关电源的变压器体积比串联稳压型电源的要小得多,电源电路比较整洁,整机重量也有所下降,所以,现在的LED驱动电源

关键字: LED 驱动电源 开关电源

LED驱动电源是把电源供应转换为特定的电压电流以驱动LED发光的电压转换器,通常情况下:LED驱动电源的输入包括高压工频交流(即市电)、低压直流、高压直流、低压高频交流(如电子变压器的输出)等。

关键字: LED 隧道灯 驱动电源
关闭