我正在编程networking标题和许多协议使用4位字段。 有一种方便的types可以用来表示这些信息吗?
我发现的最小types是BYTE。 然后,我必须使用大量的二进制操作来引用该variables中的几个位。
由于存储器是字节寻址的,因此不能寻址小于单个字节的任何单元。 不过,你可以建立你想通过网络发送的struct
,并使用如下的位域 :
struct A { unsigned int nibble1 : 4; unsigned int nibble2 : 4; };
扩展Mehrdads的答案,也使用一个字节的联盟,以避免一些邪恶的表演:
union Nibbler { struct { unsigned int first:4; unsigned int second:4; } nibbles; unsigned char byte_value; }
每个人似乎都喜欢在struct
s中使用位字段。 就个人而言,我将所有的数据包代码都包含在对象中,以免看到内容。 我发现使用位域来处理协议代码的问题是它鼓励使用结构作为内存上的覆盖。 你可以安全地做到这一点,但你必须非常小心,以确保你正确地处理永久性和包装问题。 除非你真的有充分的理由(例如,你正在编写从内存映射IO区域接收以太网数据包的代码),否则使用覆盖在内存上的位域会产生非常脆弱的代码恕我直言。
我发现编写一个Packet
类要容易得多,它可以实现各种位宽的提取,插入和覆盖例程。 然后你实现你的数据包处理代码,从提取某些宽度的值从偏移量转换为本地整数,而不是。 隐藏抽象背后的所有内存和包装问题,直到性能分析证明开销太高。
这是我希望多年前学到的那些经验教训之一…您可能认为代码的可移植性不是问题,也不是永恒性。 相信我,当你的编译器改变其填充算法,或者你切换到另一个编译器时,会引起你头痛的次数,这将使你确信覆盖对于网络数据包处理代码是一个非常糟糕的主意。
在结构中使用字段:
struct Header { unsigned int lowestNibble : 4; unsigned int anotherNibble : 4; unsigned int : 18; # Unnamed padding. bool aBool : 1; bool anotherBool : 1; unsigned int highestNibble : 4; };
: 4
表示该条目应该占用4位。 您可以使用任意数量的位。 你可以使用任何你喜欢的内置类型。
通常你最终将一个指向数据的指针指向Header *
然后执行如下操作:
pHeader->lowestNibble = 5;
不,没有方便的啃类型。 但是,使用宏或模板功能很容易。 如果/当你需要处理字节顺序的时候,这非常有效。
Foredecker