まず、移植性には関心がなく、エンディアンは変わらないと安全に推測できます。ハードウェアレジスタ値を読み取ると仮定して、ビットマスクを使用せずにレジスタ内の個々のフィールドを参照できるように、そのレジスタ値をビットフィールドにオーバーレイしたいと思います。
編集: GManによって指摘された問題を修正し、将来の読者にとってより明確になるようにコードを調整しました。
参照:より雄弁な解決策については、以下のAndersK.とMichaelJの回答を参照してください。
#include <iostream>
/// \class HardwareRegister
/// Abstracts out bitfields in a hardware register.
/// \warning This is non-portable code.
class HardwareRegister
{
public:
/// Constructor.
/// \param[in] registerValue - the value of the entire register. The
/// value will be overlayed onto the bitfields
/// defined in this class.
HardwareRegister(unsigned long registerValue = 0)
{
/// Lots of casting to get registerValue to overlay on top of the
/// bitfields
*this = *(reinterpret_cast<HardwareRegister*>(®isterValue));
}
/// Bitfields of this register.
/// The data type of this field should be the same size as the register
/// unsigned short for 16 bit register
/// unsigned long for 32 bit register.
///
/// \warning Remember endianess! Order of the following bitfields are
/// important.
/// Big Endian - Start with the most signifcant bits first.
/// Little Endian - Start with the least signifcant bits first.
unsigned long field1: 8;
unsigned long field2:16;
unsigned long field3: 8;
}; //end class Hardware
int main()
{
unsigned long registerValue = 0xFFFFFF00;
HardwareRegister testRegister(registerValue);
// Prints out for little endianess machine
// Field 1 = 0
// Field 2 = 65535
// Field 3 = 255
std::cout << "Field 1 = " << testRegister.field1 << std::endl;
std::cout << "Field 2 = " << testRegister.field2 << std::endl;
std::cout << "Field 3 = " << testRegister.field3 << std::endl;
}