我正在尝试使用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
,我们得到的数字为{ {1}}注释掉了。如果c和e(bools)相反占用8位而不是32位,我们得到#pragma pack(1)
,这是我们在176
取消注释时获得的数字。似乎#pragma pack(1)
只允许bools被自己打包成单个字节,而不是单词,而不是带有无符号整数的bool。
所以我的问题,在一句话中:有没有办法强制编译器将e到一个单词包装?相关的是这个问题:C++ bitfield packing with bools,但这不能回答我的问题;它只指出了我试图强行离开的行为。
如果确实没有办法做到这一点,有没有人有任何解决方法的想法?我很茫然,因为:
#pragma pack(1)
直接访问,所以看起来有点hacky而且,人们几乎需要智能感知或反复试验才能记住哪些需求()
,哪些不需要。()
创建一个构造函数,它接受一个testStruct
- 类型的对象),因为实际的结构很长有很多位字段指定的变量。答案 0 :(得分:5)
我建议你创建一个" normal"没有任何包装的结构。使用成员的默认POD类型。
创建用于加载" normal"的接口函数缓冲区(uint8_t)中的字段,并存储到缓冲区。
这将允许您在程序中以合理的方式使用数据成员。位打包和解包将由接口函数处理。位twiddling应使用按位AND和按位OR函数,而不依赖于结构中的位字段表示法。这将允许您调整位错,并在编译器之间更容易移植。
这就是我设计协议类的方法。而且我不必担心比特场定位,Endianess或那类事情。
另外,我可以使用块I / O来读取和写入缓冲区。
答案 1 :(得分:0)
没有使用访问器或接口层,没有简单,优雅的方法。不幸的是,没有像#pragma
这样的东西来解决这个问题。我最终只是将bool
转换为unsigned int
并重命名变量,例如f
到f_flag
或f_bool
以鼓励正确使用,并明确包含的变量。它的效率低于托马斯的解决方案,但显然并不那么强大,并且仍然可以通过任何更简单的方法解决一些主要缺点。
答案 2 :(得分:0)
发布此问题多年后,用户@WaltK将此评论添加到了链接的相关问题中:
“如果要对位字段的布局进行更多控制 存储器中的结构consider using this bit field facility, implemented as a library header file.“
答案 3 :(得分:-1)
尝试以这种方式打包:
#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)