我曾经在许多不同的嵌入式系统上工作过.他们都使用typedef
s(或#defines
)作为类型UINT32
.
这是一个很好的技术,因为它将类型的大小驱动到程序员家,让你更加意识到溢出的可能性等.
但是在某些系统上,您知道编译器和处理器在项目生命周期内不会发生变化.
那么应该影响您创建和实施项目特定类型的决策呢?
编辑我想我设法失去了我的问题的要点,也许它真的是两个.
使用嵌入式编程,您可能需要特定大小的接口类型,以及处理受限资源(如RAM).这是无法避免的,但您可以选择使用编译器中的基本类型.
对于其他一切,类型的重要性较低.
您需要注意不要引起溢出,并且可能需要注意寄存器和堆栈的使用.这可能会引导你UINT16
,UCHAR
.但是使用类型UCHAR
可以添加编译器'fluff'.由于寄存器通常较大,因此某些编译器可能会添加代码以强制将结果输入类型.
__PRE__可以变成
__PRE__这是不必要的.
所以我认为我的问题应该是: -
鉴于嵌入式软件的限制,为一个项目设置的最佳策略是什么,这个项目将有很多人参与其中 - 并非所有人都具有相同的经验水平.
小智 17
我很少使用类型抽象.以下是我的论点,按主观性的递增顺序排序:
局部变量与结构成员和数组的不同之处在于您希望它们适合寄存器.在32b/64b目标上,本地int16_t
可以使代码比本地int更慢,因为编译器必须根据语义向/ force/overflow添加操作int16_t
.虽然C99定义了一个intfast_t
typedef,但是AFAIK一个普通的int也适合寄存器,它肯定是一个较短的名字.
喜欢这些typedef的组织几乎总是最终得到其中几个(INT32, int32_t, INT32_T
无限广告).因此,使用内置类型的组织在某种程度上只有一组名称会更好.我希望人们使用stdint.h或windows.h中的typedef或任何现有的; 当一个目标没有那个.h文件时,加一个目标有多难?
从理论上讲,typedef可以帮助实现可移植性,但是,我从来没有从中获得过一些东西.有没有一个有用的系统可以从32b目标移植到16b目标?是否有一个16b系统,移植到32b目标是不是很容易?此外,如果大多数变量都是整数,那么你实际上会从新目标的32位获得一些东西,但如果它们是int16_t
你不会.而难以移植的地方往往需要人工检查; 在尝试端口之前,您不知道它们在哪里.现在,如果有人认为如果你在所有地方都有typedef就可以轻松移植东西 - 当端口出现时,很少有系统发生,编写一个脚本来转换代码库中的所有名称.这应该按照"无需人工检查"逻辑工作,并将工作推迟到实际带来好处的时间点.
现在,如果可移植性可能是typedef的理论上的好处,那么可读性肯定会降低.看看stdint.h : {int,uint}{max,fast,least}{8,16,32,64}_t
. 很多类型.程序有很多变量; 它真的很容易理解哪些需要int_fast16_t
,哪些需要uint_least32_t
?我们有多少次默默地在他们之间转换,使他们完全没有意义?(我特别喜欢BOOL/Bool/eBool/boolean/bool/int转换.每个由有序组织强制命令类型的程序编写的程序都充斥着它).
当然在C++中,我们可以通过在模板类实例化中使用重载运算符和东西包装数字来使类型系统更加严格.这意味着您现在将获得"class Number <int,Least,32>"的错误消息,对于类型类型<unsigned long long,Fast,64>的参数,没有运算符+重载,候选者是..."I也不要称之为"可读性".您正确实现这些包装类的机会是微观的,并且大多数时候您将等待无数的模板实例化进行编译.
C99标准有许多标准大小的整数类型.如果您可以使用支持C99(gcc)的编译器,<stdint.h>
您可以在其中找到它们,您可以在项目中使用它们.
此外,在嵌入式项目中使用类型作为单元转换之类的"安全网"尤其重要.如果你可以使用C++,我知道有一些"单元"库可以让你在由C++类型系统(通过模板)定义的物理单元中工作,这些物理单元被编译为底层标量类型的操作.例如,这些库不允许您添加distance_t
到a,mass_t
因为单元不排队; 你实际上会得到一个编译器错误.
即使您不能使用C++或其他允许您以这种方式编写代码的语言,您至少可以使用C类型系统来帮助您通过眼睛捕获错误.(这实际上是西蒙尼的匈牙利命名法的原意.)仅仅因为编译器不会冲你大吼大叫用于添加meter_t
到gram_t
并不意味着你不应该使用类型那样.然后,代码审查将更有效地发现单位错误.