Kei*_*h M 4 c++ struct pragma pack bit-fields
我正在尝试使用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;
}
(如果不清楚,在实际程序中,基本的想法是程序null*从与Ada代码通信的内容中获取并将其转换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)只允许将bool自身打包成单个字节,而不是单词,而不是带有无符号整数的bool.
所以我的问题,用一句话来说:有没有办法强制编译器将e到e包装成一个单词?相关的是这个问题:C++ bitfield打包用bool,但这不回答我的问题; 它只指出了我试图强行离开的行为.
如果真的没有办法做到这一点,有没有人有任何解决方法的想法?我不知所措,因为:
()后续的情况下直接访问的,所以它看起来有点hacky和obtuse,而且几乎需要智能感知或反复试验以记住哪些需求(),哪些不需要.testStruct一个单一testStructImport类型的对象),因为实际的结构很长,有很多位字段指定的变量.我建议您创建一个"普通"结构,不要任何打包.使用成员的默认POD类型.
创建接口函数,用于从缓冲区(uint8_t)加载"普通"字段,并存储到缓冲区.
这将允许您在程序中以合理的方式使用数据成员.位打包和解包将由接口函数处理.bit twiddling应使用按位AND和按位OR函数,而不依赖于结构中的位字段表示法.这将允许您调整位错,并在编译器之间更容易移植.
这就是我设计协议类的方法.而且我不必担心比特字段定位,Endianess或类似的东西.
此外,我可以使用块I/O来读取和写入缓冲区.
如果不使用访问器或接口层,就没有简单、优雅的方法。不幸的是,没有什么办法#pragma可以解决这个问题。我最终只是将bools 转换为unsigned int并将变量从 eg 重命名f为f_flagorf_bool以鼓励正确使用并明确变量包含的内容。它比托马斯的解决方案省力,但显然没有那么强大,并且仍然克服了任何更简单的方法的一些主要缺点。