位欄位

可以使用簡單的位欄位來描述可能涉及特定位數的事物。

struct encoderPosition {
   unsigned int encoderCounts : 23;
   unsigned int encoderTurns  : 4;
   unsigned int _reserved     : 5;
};

在這個例子中,我們考慮一個具有 23 位單精度和 4 位來描述多圈的編碼器。當與輸出與特定位數相關聯的資料的硬體介面時,經常使用位欄位。另一個例子可能是與 FPGA 通訊,其中 FPGA 以 32 位部分將資料寫入儲存器,允許硬體讀取:

struct FPGAInfo {
    union {
        struct bits {
            unsigned int bulb1On  : 1;
            unsigned int bulb2On  : 1;
            unsigned int bulb1Off : 1;
            unsigned int bulb2Off : 1;
            unsigned int jetOn    : 1;
        };
        unsigned int data;
   };
};

在這個例子中,我們展示了一個常用的構造,能夠訪問各個位的資料,或者整個資料包的寫入(模擬 FPGA 可能做的事情)。然後我們可以訪問這樣的位:

FPGAInfo fInfo;
fInfo.data = 0xFF34F;
if (fInfo.bits.bulb1On) {
    printf("Bulb 1 is on\n");
}

這是有效的,但根據 C99 標準 6.7.2.1,第 10 項:

單元內的位域分配順序(高階到低階或低階到高階)是實現定義的。

以這種方式定義位域時,你需要注意位元組序。因此,可能需要使用預處理程式指令來檢查機器的位元組順序。一個例子如下:

typedef union {
    struct bits {
#if defined(WIN32) || defined(LITTLE_ENDIAN)
    uint8_t commFailure :1;
    uint8_t hardwareFailure :1;
    uint8_t _reserved :6;
#else
    uint8_t _reserved :6;
    uint8_t hardwareFailure :1;
    uint8_t commFailure :1;
#endif
    };
    uint8_t data;
} hardwareStatus;