有没有一种不使用位域的简单方法来读取/写入字节中的半字节?我总是需要读取两个半字节,但需要分别写入每个半字节。
谢谢!
谢谢!
使用遮罩:
char byte;
byte = (byte & 0xF0) | (nibble1 & 0xF); // write low quartet
byte = (byte & 0x0F) | ((nibble2 & 0xF) << 4); // write high quartet
您可能希望将此放在宏中。
// Fixed-width integer types
#include <cstdint>
// Constexpr construction
constexpr uint8_t makeByte(uint8_t highNibble, uint8_t lowNibble)
{
return (((highNibble & 0xF) << 4) | ((lowNibble & 0xF) << 0));
}
// Constexpr high nibble extraction
constexpr uint8_t getHighNibble(uint8_t byte)
{
return ((byte >> 4) & 0xF);
}
// Constexpr low nibble extraction
constexpr uint8_t getLowNibble(uint8_t byte)
{
return ((byte >> 0) & 0xF);
}
主要优点:
union
技巧contexpr
函数
(在任何人提问之前,>> 0
和<< 0
主要是为了视觉平衡,以展示即使在实际上不需要移位的特殊情况下,相同的概念也在使用中。如果您的编译器不能将其优化掉,请向您的编译器提供商投诉,而不是我。)
然而,如果你的 nibbles 实际上代表了重要的内容,例如位域, 那么你也许想要创建一个 class
/struct
。
例如,如果你正在编写一个需要带有索引 16 色值的帧缓冲器的设备,每两个像素值打包成一个字节,你可能会想要创建这样的东西:
struct PixelPair
{
private:
uint8_t value;
public:
contexpr explicit PixelPair(uint8_t rawValue) :
value { rawValue }
{
}
constexpr PixelPair(uint8_t leftPixel, uint8_t rightPixel) :
value { makeByte(leftPixel, rightPixel) }
{
}
constexpr uint8_t getLeftPixel() const
{
return getHighNibble(this->value);
}
constexpr uint8_t getRightPixel() const
{
return getLowNibble(this->value);
}
constexpr uint8_t getRawValue() const
{
return this->value;
}
};
uint8_t
和特定指定的PixelPair
。(另请参见:Bjarne Stroustrup's 2012 Keynote,他在其中讨论了“类型丰富的编程”)。pixelPair.getLeftPixel()
告诉您代码正在处理什么:一对像素的左侧像素。pixelPair.getLeftPixel()
告诉您该函数正在检索左侧像素,而没有指定如何检索,而getHighNibble(pixelByte)
只告诉您如何检索高位半字节,它并没有告诉您该半字节代表什么 - 也许高位半字节实际上代表右侧像素?Pixel
类,如果你想要更多的类型安全性,它可以具有处理特定像素格式相关功能。这种类型的代码让你思考你正在处理什么样的数据以及数据之间的关系,而不仅仅是将数据视为位和字节的数量。union ByteNibbles
{
ByteNibbles(BYTE hiNibble, BYTE loNibble)
{
data = loNibble;
data |= hiNibble << 4;
}
BYTE data;
};
使用方法如下:
ByteNibbles byteNibbles(0xA, 0xB);
BYTE data = byteNibbles.data;
makeByte(high,low)
函数即可。 - Pharap
byte
中的半字节。byte = (byte & ~0xF) | (nibble1 & 0xF)
,对于高半字节同样如此。 - Mike Seymour~
。 - Paul R