位字段
可以使用简单的位字段来描述可能涉及特定位数的事物。
struct encoderPosition {
unsigned int encoderCounts : 23;
unsigned int encoderTurns : 4;
unsigned int _reserved : 5;
};
在这个例子中,我们考虑一个具有 23 位单精度和 4 位来描述多圈的编码器。当与输出与特定位数相关联的数据的硬件接口时,经常使用位字段。另一个例子可能是与 FPGA 通信,其中 FPGA 以 32 位部分将数据写入存储器,允许硬件读取:
struct FPGAInfo {
union {
struct bits {
unsigned int bulb1On : 1;
unsigned int bulb2On : 1;
unsigned int bulb1Off : 1;
unsigned int bulb2Off : 1;
unsigned int jetOn : 1;
};
unsigned int data;
};
};
在这个例子中,我们展示了一个常用的构造,能够访问各个位的数据,或者整个数据包的写入(模拟 FPGA 可能做的事情)。然后我们可以访问这样的位:
FPGAInfo fInfo;
fInfo.data = 0xFF34F;
if (fInfo.bits.bulb1On) {
printf("Bulb 1 is on\n");
}
这是有效的,但根据 C99 标准 6.7.2.1,第 10 项:
单元内的位域分配顺序(高阶到低阶或低阶到高阶)是实现定义的。
以这种方式定义位域时,你需要注意字节序。因此,可能需要使用预处理程序指令来检查机器的字节顺序。一个例子如下:
typedef union {
struct bits {
#if defined(WIN32) || defined(LITTLE_ENDIAN)
uint8_t commFailure :1;
uint8_t hardwareFailure :1;
uint8_t _reserved :6;
#else
uint8_t _reserved :6;
uint8_t hardwareFailure :1;
uint8_t commFailure :1;
#endif
};
uint8_t data;
} hardwareStatus;