对于嵌入式开发人员来说,编写可重用、可移植且经得起时间考验的软件至关重要。下面是在C中创建和使用可移植类型的7个技巧。
技巧1 – 使用stdint.h
使用内置数据类型会导致不同编译器之间的可移植性问题。C标准没有指定整数的存储大小,这导致一些编译器供应商使用2或4个字节来存储整数,结果可能是灾难性的。
使用内置数据类型的安全替代方法是使用stdint.h固定宽度整数。这些数据类型uint8_t、int8_t、uint16_t、int16_t、uint32_t和int32_t指定存储数据所需的存储位数。移植这些数据类型中的任何一种都会在任何编译器中导致相同的行为,并且不会导致四个字节的存储突然变成两个字节。
技巧2 – 使用stdbool.h
开发人员有时可能会决定他们想要一种可以存储简单的真或假值的数据类型。通过包含stdbool.h,可以将标准布尔数据类型及其真或假定义引入到项目中。
提示3 – 不要自定义定义 TRUE、FALSE、bool
在上一个技巧中,推荐使用标准库文件 stdbool.h。一些嵌入式开发人员可能没有意识到 stdbool 的存在,或者可能决定不使用它。相反,他们自定义定义 bool、true 和 false。这样做的问题是,当移植具有自定义版本的代码时,可能会发生不匹配,即尝试重新定义 true、false 和 bool 并且编译器会抱怨。不要创建自己的版本,只需遵循技巧2。
技巧4 – 远离自定义整数类型
使用 typedef 创建简洁明了的类型名称是编写嵌入式软件的好方法。当开发人员开始定义看起来非常接近标准整数类型的非标准整数类型时,问题就出现了。例如,取下面的自定义类型
typedef volatile uint16_t vuint16_t;
在软件中看到 vuint16_t 会令人困惑。v是什么? 混淆 volatile 关键字可能很危险! 不应该强迫开发人员编写 volatile 以便阅读代码的开发人员知道该变量是 volatile 吗? 读取 vuint16_t 很容易被误读为 uint16_t 或更糟糕的是,嵌入式开发人员可能会意外键入 uint16_t 并完全错过 v。
坚持使用标准类型,并在任何阅读或维护代码的人面前直接使用 volatile 等重要关键字。
技巧5 – 自定义类型应该有 _t
定义自定义类型时,使用 _t 来匹配固定宽度的整数类型,它简单明了。以以下为例;
typedef enum
{
STATE_1,
STATE_2
}State_t;
很明显,State_t 是一个 typedef。
技巧6 – 使用枚举自定义类型
创建类似于技巧5中所示的自定义数据类型可以大大提高嵌入式软件的可读性和可维护性。在#define 定义上使用枚举有很多优点。enum 的使用易于维护,移植(甚至到 C++)和 enum 将显示在调试器监视窗口中。对枚举进行类型定义的能力是 C 语言中非常强大的工具,因此请明智地使用它!
技巧7 – 不要混淆底层类型
使用 typedef 的危险之一是很容易混淆底层类型。例如,如果新类型未正确命名,则结构的 typedef 可以隐藏数据是结构的事实。嵌入式开发人员应该能够阅读和识别数据的底层类型,而无需搜索文档或源代码。回顾技巧4,用 v 掩盖 volatile 是相同的想法,生成的数据类型需要以简洁明了的方式清楚地表明它所代表的内容