在 Windows C/C++ 中使用半字节(4 位变量)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/863575/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 17:38:35  来源:igfitidea点击:

Using nibbles (4 bits variables) in windows C/C++

c++cwindowstypes

提问by Eric

I'm programming network headers and a lot of protocols use 4 bits fields. Is there a convenient type I can use to represent this information?

我正在编写网络标头,许多协议使用 4 位字段。有没有一种方便的类型可以用来表示这些信息?

The smallest type I've found is a BYTE. I must then use a lot of binary operations to reference only a few bits inside that variable.

我发现的最小类型是 BYTE。然后我必须使用大量的二元运算来仅引用该变量中的几个位。

回答by Mehrdad Afshari

Since the memory is byte-addressed, you can't address any unit smaller than a single byte. However, you can build the structyou want to send over the network and use bit fieldslike this:

由于内存是字节寻址的,因此您无法寻址任何小于单个字节的单元。但是,您可以构建struct要通过网络发送的内容并使用如下位字段

struct A {
   unsigned int nibble1 : 4;
   unsigned int nibble2 : 4;
};

回答by Christoffer

Expanding on Mehrdads answer, also use a union with a byte in order to avoid some evil-looking casts:

扩展 Mehrdads 的答案,还使用带有字节的联合以避免一些看起来很邪恶的强制转换:

union Nibbler {
     struct { 
        unsigned int first:4;
        unsigned int second:4;
     } nibbles;
     unsigned char byte_value;
}

回答by D.Shawley

Everyone seems to like using bit-fields in structs for this. Personally, I wrap all of my packet code in objects so that you don't see the guts. The problem that I have found with using bit-fields for protocol code is that it encourages using structures as overlays on memory. You can do this safely, but you have to be excruciatingly careful to ensure that you are properly dealing with endianess and packing issues. Unless you really have a good reason (e.g., you're writing the code that receives the Ethernet packet from the memory-mapped IO region), then using bit-fields overlaid on memory produces extremely fragile code IMHO.

每个人似乎都喜欢struct为此使用s 中的位域。就个人而言,我将所有数据包代码都包装在对象中,这样您就看不到胆量了。我发现使用位域作为协议代码的问题是它鼓励使用结构作为内存的覆盖。您可以安全地执行此操作,但您必须非常小心,以确保正确处理字节序和打包问题。除非您真的有充分的理由(例如,您正在编写从内存映射 IO 区域接收以太网数据包的代码),否则使用覆盖在内存上的位域会产生极其脆弱的代码恕我直言。

I find it much easier to write a Packetclass that implements extraction, insertion, and overwriting routines in various bit widths. Then you implement your packet processing code in terms of extracting values of certain widths from offsets into native integers and what not. Hide all of the endianess and packing issues behind an abstraction until profiling proves that the overhead is too great to bear.

我发现编写一个Packet以各种位宽实现提取、插入和覆盖例程的类要容易得多。然后你实现你的数据包处理代码,从偏移量中提取某些宽度的值到本机整数和什么不是。隐藏抽象背后的所有字节序和打包问题,直到分析证明开销太大而无法承受。

This is one of those lessons that I wish I had learned years ago... you might think that portability of code isn't a problem and neither is endianess. Trust me, the number of headaches that this causes you when your compiler changes its padding algorithm or you switch to a different compiler will convince you that overlays are a very badidea for network packet processing code.

这是我希望我多年前学到的教训之一……您可能认为代码的可移植性不是问题,字节序也不是问题。相信我,当您的编译器更改其填充算法或切换到不同的编译器时,这会给您带来多少麻烦,这将使您相信覆盖对于网络数据包处理代码来说是一个非常糟糕的主意。

回答by Jon-Eric

Use fields in a struct:

在结构中使用字段:

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;
};

The : 4indicates that entry should occupy 4 bits. You can use any number of bits you like. You can use any built in type you like.

: 4指示条目应该占据4位。您可以使用任意数量的位。您可以使用任何您喜欢的内置类型。

Typically you end up casting a pointer to your data to a Header *then doing something like:

通常,您最终会将指向您的数据的指针投射到 aHeader *然后执行以下操作:

pHeader->lowestNibble = 5;

回答by Foredecker

No, there are no convenient types for nibbles. But, its easy to make them with macros or with template functions. This works well espeicaly if/when you need to deal with endian-ness.

不,没有方便的半字节类型。但是,使用宏或模板函数很容易制作它们。如果/当您需要处理字节序时,这特别有效。

Foredecker

前甲板