簡體   English   中英

用比特場包裝bools(C ++)

[英]Packing bools with bit field (C++)

我正在嘗試使用C ++與Ada代碼進行交互,因此我使用位字段定義結構,以便所有數據在兩種語言中都處於相同的位置。 以下不是我正在做的,但概述了問題。 以下也是VS2008中的控制台應用程序,但這不是超級相關的。

using namespace System;
int main() {
    int array1[2] = {0, 0};
    int *array2 = new int[2]();
    array2[0] = 0;
    array2[1] = 0;

    #pragma pack(1)
    struct testStruct {
        // Word 0 (desired)
        unsigned a : 8;
        unsigned b : 1;
        bool c : 1;
        unsigned d : 21;
        bool e : 1;

        // Word 1 (desired)
        int f : 32;

        // Words 2-3 (desired)
        int g[2]; //Cannot assign bit field but takes 64 bits in my compiler
    };
    testStruct test;

    Console::WriteLine("size of char: {0:D}", sizeof(char) * 8);
    Console::WriteLine("size of short: {0:D}", sizeof(short) * 8);
    Console::WriteLine("size of int: {0:D}", sizeof(int) * 8);
    Console::WriteLine("size of unsigned: {0:D}", sizeof(unsigned) * 8);
    Console::WriteLine("size of long: {0:D}", sizeof(long) * 8);
    Console::WriteLine("size of long long: {0:D}", sizeof(long long) * 8);
    Console::WriteLine("size of bool: {0:D}", sizeof(bool) * 8);
    Console::WriteLine("size of int[2]: {0:D}", sizeof(array1) * 8);
    Console::WriteLine("size of int*: {0:D}", sizeof(array2) * 8);
    Console::WriteLine("size of testStruct: {0:D}", sizeof(testStruct) * 8);
    Console::WriteLine("size of test: {0:D}", sizeof(test) * 8);

    Console::ReadKey(true);

    delete[] array2;
    return 0;
}

(如果不清楚,在實際程序中,我認為基本的想法是程序從與Ada代碼通信的內容中獲取null*並將其轉換為testStruct*以訪問數據。)

#pragma pack(1)注釋掉后,輸出為:

size of char: 8
size of short: 16
size of int: 32
size of unsigned: 32
size of long: 32
size of long long: 64
size of bool: 8
size of int[2]: 64
size of int*: 32
size of testStruct: 224
size of test: 224

顯然4個字(索引0-3)應該是4 * 4 * 8 = 32 * 4 = 128位,而不是224.其他輸出行有助於確認VS2008編譯器下類型的大小。

隨着#pragma pack(1)取消注釋,該數字(在最后兩行輸出中)減少到176 ,仍然大於128.似乎bool沒有與“Word中的無符號整數”打包在一起0" 。

注意:a&b,c,d,e,f,用不同的單詞打包為5,+ 2為數組= 7個單詞,乘以32位= 224 ,我們用#pragma pack(1)得到的數字被注釋掉。 如果c和e(bools)相反占用8位而不是32位,我們得到176 ,這是我們用#pragma pack(1)取消注釋的數字。 似乎#pragma pack(1)只允許bools被自己打包成單個字節,而不是單詞,而不是帶有無符號整數的bool。

所以我的問題,用一句話來說:有沒有辦法強制編譯器將e到e包裝成一個單詞? 相關的是這個問題: C ++ bitfield打包用bool ,但這不回答我的問題; 它只指出了我試圖強行離開的行為。

如果真的沒有辦法做到這一點,有沒有人有任何解決方法的想法? 我不知所措,因為:

  1. 我被要求避免更改我正在復制的結構格式(沒有重新排序)。
  2. 我不想將bool更改為無符號整數,因為它可能會導致問題,不斷重新將其重新強制轉換為bool並且可能意外地使用了錯誤版本的重載函數,更不用說使代碼更加模糊了對於后來閱讀它的人。
  3. 我不想將它們聲明為私有無符號的int然后創建公共訪問器或者其他東西,因為項目中所有其他結構的所有其他成員都是在沒有()之后直接訪問的,所以它看起來有點hacky和obtuse,並且會幾乎需要IntelliSense或反復試驗來記住哪些需求() ,哪些不需要。
  4. 我想避免為數據轉換創建另一個結構類型(例如,為testStruct創建一個接受單個testStructImport類型對象的testStructImport函數),因為實際結構很長,有很多位字段指定的變量。

我建議您創建一個“普通”結構,不要任何打包。 使用成員的默認POD類型。

創建接口函數,用於從緩沖區(uint8_t)加載“普通”字段,並存儲到緩沖區。

這將允許您在程序中以合理的方式使用數據成員。 位打包和解包將由接口函數處理。 位twiddling應使用按位AND和按位OR函數,而不依賴於結構中的位字段表示法。 這將允許您調整位錯,並在編譯器之間更容易移植。

這就是我設計協議類的方法。 而且我不必擔心比特字段定位,Endianess或類似的東西。

此外,我可以使用塊I / O來讀取和寫入緩沖區。

嘗試以這種方式打包:

    #pragma pack( push, 1 )
struct testStruct {
    // Word 0 (desired)
    unsigned a : 8;
    unsigned b : 1;
    unsigned c : 1;
    unsigned d : 21;
    unsigned e : 1;

    // Word 1 (desired)
    unsigned f : 32;

    // Words 2-3 (desired)
    unsigned g[2]; //Cannot assign bit field but takes 64 bits in my compiler
};
#pragma pack(pop)

沒有使用訪問器或接口層,沒有簡單,優雅的方法。 不幸的是,沒有什么比#pragma解決這個問題了。 我最終只是將bool s轉換為unsigned int並將變量從例如f重命名為f_flagf_bool以鼓勵正確使用並明確包含的變量。 它比Thomas的解決方案更省力,但顯然並不那么強大,並且仍然可以通過任何更簡單的方法解決一些主要缺點。

在我發布此問題多年后,用戶@WaltK將此評論添加到鏈接的相關問題中:

“如果你想更好地控制內存中位域結構的布局,可以考慮使用這個位字段工具,實現為庫頭文件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM