我正在编程网络标头,许多协议使用4位字段。我可以使用方便的类型来表示这些信息吗?
我发现的最小型是BYTE。然后我必须使用大量的二进制操作来仅引用该变量中的几个位。
答案 0 :(得分:31)
由于存储器是字节寻址的,因此不能寻址小于单个字节的任何单元。但是,您可以构建要通过网络发送的struct
并使用bit fields,如下所示:
struct A {
unsigned int nibble1 : 4;
unsigned int nibble2 : 4;
};
答案 1 :(得分:15)
扩展Mehrdads的答案,也使用带字节的联合,以避免一些看似邪恶的演员:
union Nibbler {
struct {
unsigned int first:4;
unsigned int second:4;
} nibbles;
unsigned char byte_value;
}
答案 2 :(得分:6)
每个人似乎都喜欢在struct
中使用位字段。就个人而言,我将所有的数据包代码都包装在对象中,这样你就看不到内容了。我在使用协议代码的位字段时发现的问题是它鼓励使用结构作为内存上的叠加。你可以安全地做到这一点,但你必须非常小心,以确保你正确处理endianess和包装问题。除非你真的有充分的理由(例如,你正在编写从内存映射IO区域接收以太网数据包的代码),否则使用内存上覆盖的位字段会产生极其脆弱的代码恕我直言。
我发现编写一个Packet
类可以更容易地实现各种位宽的提取,插入和覆盖例程。然后,您可以根据从偏移量中提取特定宽度的值到本机整数以及未提取的值来实现数据包处理代码。隐藏抽象背后的所有endianess和打包问题,直到分析证明开销太大而无法承受。
这是我希望多年前学过的课程之一......您可能会认为代码的可移植性不是问题,也不是endianess。相信我,当您的编译器更改其填充算法或切换到不同的编译器时,这会导致您的头痛次数将说服您叠加是网络数据包处理代码的非常糟糕的想法。
答案 3 :(得分:3)
使用结构中的字段:
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;
答案 4 :(得分:-2)
不,半字节没有方便的类型。但是,它很容易用宏或模板功能。如果/当你需要处理字节序时,这很有效。
Foredecker