我使用各种微控制器体系结构/字长来开发嵌入式系统的固件,并尽可能强调可移植性。我的问题是如何生成/应用比特掩码和标志,以确保安全和可移植性,并对于任何非通用代码,角落案例是什么。
比特掩码
#define MASK_8_V1(x) ((x) & 0xFF)
#define MASK_8_V2(x) ((x) & 0x00FF)
a = MASK_8_V1(b)
a = MASK_8_V2(b)
这两个版本是否总是保证获取a的宽度值,其中除了b的低8位之外,所有位都被清零?如果需要,它们应该进行符号扩展,这两个版本是否有任何区别?
标志
#define GEN_FLAG_16(x) ((0xFFFF) & ((unsigned) 1 << (x)))
#define GEN_FLAG_32(x) ((0xFFFFFFFF) & ((unsigned long) 1 << (x)))
如果我需要一个生成标志常量的通用宏,这是否总是会生成列出宽度的标志常量? 两者都可以。
#define CHECK_FLAG_16(x, y) ((x) & GEN_FLAG_16(y))
#define CHECK_FLAG_32(x, y) ((x) & GEN_FLAG_32(y))
if(CHECK_FLAG_16(a, b))
{
// Do something.
}
结合前面的场景,如果b的原始值中所需的位被设置,这段代码是否总是会执行内部代码?
对于所有情况,请假设:
- C90或C99兼容编译器 - a和b可以是任意组合的本机C类型,带符号或无符号 - x始终评估为正整数类型 - 任意本机字大小
请注意提到使用stdint.h的内容:我最近遇到一个问题,需要将我撰写的串行协议处理程序移植到另一个微控制器系列上,但发现RAM不可按字节寻址。我们最终删除了所有uint8_t的使用,并进行了修改以适应16位可寻址内存。这让我想知道是否可以使用本机C类型以不需要以后进行修改的方式实现它。我的问题间接来自那个问题。
0xff
和0x00000000ff
有什么不同?为什么不使用专门定义用于固定宽度数据的固定宽度类型?请参阅stdint.h
!另外,不要使用带符号整数。 - too honest for this sitestdint.h
,并且近年来开发的所有代码都遵循这个规则。最近我遇到了一个问题,需要将我编写的串行协议处理程序移植到另一种微控制器系列,结果发现 RAM 不是按字节寻址的。我们最终删除了所有 uint8_t 的使用,并进行了修改以适应 16 位可寻址内存。这让我想知道是否可以使用本机 C 类型以不同的方式实现它,以避免后期修改。我的问题间接地来源于那个问题。 - derrickunsigned
了。 - derrick