比特操纵良好做法

作为一名初学C程序员,我想知道,在设备中设置控制位的最佳易读性和易于理解的解决方案是什么.有标准吗?任何模仿的示例代码?谷歌没有给出任何可靠的答案.

例如,我有一个控制块映射:
map

我看到的第一种方法是简单地设置所需的位.它在评论中需要一堆解释,似乎并不是那么专业.

DMA_base_ptr[DMA_CONTROL_OFFS] = 0b10001100;

我看到的第二种方法是创建一个位字段.我不确定这是否应该坚持,因为我从未遇到过以这种方式使用它(与我提到的第一个选项不同).

struct DMA_control_block_struct
{ 
    unsigned int BYTE:1; 
    unsigned int HW:1; 
    // etc
} DMA_control_block_struct;

其中一个选项比另一个更好吗?有什么选择我只是看不到吗?

任何建议都将受到高度赞赏

位字段的问题在于C标准没有规定它们的定义顺序与它们的实现顺序相同.所以你可能没有设置你认为你的位.

C standard州第6.7.2.1p11节:

An implementation may allocate any addressable storage unit large
enough to hold a bit- field. If enough space remains, a bit-field
that immediately follows another bit-field in a structure shall be
packed into adjacent bits of the same unit. If insufficient space
remains, whether a bit-field that does not fit is put into
the next unit or overlaps adjacent units is
implementation-defined. The order of allocation of bit-fields within
a unit (high-order to low-order or low-order to high-order) is
implementation-defined.
The alignment of the addressable storage
unit is unspecified.

例如,从Linux上的/usr/include/netinet/ip.h文件文件中查看struct iphdr的定义,它表示IP头:

struct iphdr
  {
#if __BYTE_ORDER == __LITTLE_ENDIAN
    unsigned int ihl:4;
    unsigned int version:4;
#elif __BYTE_ORDER == __BIG_ENDIAN
    unsigned int version:4;
    unsigned int ihl:4;
#else
# error "Please fix <bits/endian.h>"
#endif
    u_int8_t tos;
    ...

您可以在此处看到,根据实现,位域的放置顺序不同.您也不应该使用此特定检查,因为此行为取决于系统.这个文件是可以接受的,因为它是系统的一部分.其他系统可以以不同方式实现这一点.

所以不要使用位域.

最好的方法是设置所需的位.但是,为每个位定义命名常量并对要设置的常量执行按位OR是有意义的.例如:

const uint8_t BIT_BYTE =     0x1;
const uint8_t BIT_HW   =     0x2;
const uint8_t BIT_WORD =     0x4;
const uint8_t BIT_GO   =     0x8;
const uint8_t BIT_I_EN =     0x10;
const uint8_t BIT_REEN =     0x20;
const uint8_t BIT_WEEN =     0x40;
const uint8_t BIT_LEEN =     0x80;

DMA_base_ptr[DMA_CONTROL_OFFS] = BIT_LEEN | BIT_GO | BIT_WORD;
相关文章
相关标签/搜索