[英]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 ,但這不回答我的問題; 它只指出了我試圖強行離開的行為。
如果真的沒有辦法做到這一點,有沒有人有任何解決方法的想法? 我不知所措,因為:
()
之后直接訪問的,所以它看起來有點hacky和obtuse,並且會幾乎需要IntelliSense或反復試驗來記住哪些需求()
,哪些不需要。 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_flag
或f_bool
以鼓勵正確使用並明確包含的變量。 它比Thomas的解決方案更省力,但顯然並不那么強大,並且仍然可以通過任何更簡單的方法解決一些主要缺點。
在我發布此問題多年后,用戶@WaltK將此評論添加到鏈接的相關問題中:
“如果你想更好地控制內存中位域結構的布局,可以考慮使用這個位字段工具,實現為庫頭文件。 ”
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.