C++:无法在按位函数后将类型 int 设置为 non-scalar

C++: Unable to set type int to non-scalar after bitwise functions

我有两个位域:(1) 一个用于处理帧 (header),(2) 另一个用于处理帧内的子帧 (identityFieldO2M)。

union header
{
    unsigned char arr[16]; // 128 bytes allocated

    BitFieldMember<0, 1> SOF;
    BitFieldMember<1, 11> BID;
    BitFieldMember<12, 1> SRR;
    BitFieldMember<13, 1> IDE;
    BitFieldMember<14, 18> IDEX;
    BitFieldMember<32, 1> RTR;
    BitFieldMember<33, 1> r1;
    BitFieldMember<34, 1> r0;
    BitFieldMember<35, 4> DLC;
    BitFieldMember<39, 8> DataField1;
    BitFieldMember<47, 15> CRC;
    BitFieldMember<62, 1> CRCDelim;
    BitFieldMember<63, 1> ACKSlot;
    BitFieldMember<64, 1> ACKdelim;
    BitFieldMember<65, 7> eof;
};

union identityFieldO2M
{
    unsigned char arr[5]; // 3 bytes allocated though only need 29 bits

    BitFieldMember<0, 2> RCI;
    BitFieldMember<2, 14> DOC;
    BitFieldMember<16, 1> PVT;
    BitFieldMember<17, 1> LCL;
    BitFieldMember<18, 1> FSB;
    BitFieldMember<19, 7> SourceFID;
    BitFieldMember<26, 3> LCC;
};

我需要先处理第一个位域,然后我将这个位域的两个成员组合起来,然后 运行 它们的组合输出到另一个位域以确定子帧。然而,我遇到的问题是,当我执行按位函数来组合两个位域时,我无法将此数据传回位域。

我想我做错了什么 "duh" 但我想不通。下面是我的实现:

    int main()
    {
    header a;
    memset(a.arr, 0, sizeof(a.arr));
    a = {0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0,0xA0}; // 1010 0000

    cout << hex << a.SOF << endl; // 1 -> 1
    cout << hex << a.BID << endl; // 010 0000 1010 -> 20a
    cout << hex << a.SRR << endl; // 0 -> 0
    cout << hex << a.IDE << endl; // 0 -> 0
    cout << hex << a.IDEX << endl; // 00 1010 0000 1010 0000 -> a0a0
    cout << hex << a.RTR << endl; // 1 -> 1
    cout << hex << a.r1 << endl; // 0 -> 0
    cout << hex << a.r0 << endl; // 1 -> 1
    cout << hex << a.DLC << endl; // 0 000 -> 0
    cout << hex << a.DataField1 << endl; // 0 1010 000 -> 50
    cout << hex << a.CRC << endl; // 0 1010 0000 1010 00 -> 2828
    cout << hex << a.CRCDelim << endl; // 0 -> 0
    cout << hex << a.ACKSlot << endl; // 0 -> 0
    cout << hex << a.ACKdelim << endl; // 1 -> 1
    cout << hex << a.eof << endl; // 010 0000 -> 20

    int BID = a.BID;
    int IDEX = a.IDEX;    
    int result = (BID<<18) | IDEX; // concatenate BID and IDEX together to get 29 bit header

    cout << "test" << endl;
    cout << "BID: " << hex << BID << endl; //-> 20a -> 010 0000 1010
    cout << "IDEX: " << hex << IDEX << endl; //-> a0a0-> 00 1010 0000 1010 0000
    cout << "Identifier Field: " << hex << result << endl; //-> 828a0a0 -> 01 0000 0101 0001 01 0 0 0 0010100 000    
    cout << "Size of Bitfield header: " << sizeof(a) << endl;

    identityFieldO2M b;
    b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
    memset(b.arr,0,sizeof(b.arr));

    cout << hex << b.RCI << endl; // 01 -> 0x01
    cout << hex << b.DOC << endl; // 0000 0101 0001 01 -> 0x145
    cout << hex << b.PVT << endl; // 0 -> 0x00
    cout << hex << b.LCL << endl; // 0 -> 0x00
    cout << hex << b.FSB << endl; // 0 -> 0x00
    cout << hex << b.SourceFID << endl; // 0010100 -> 0x14
    cout << hex << b.LCC << endl; // 000 -> 0 -> 0x00

    sleep(100);
    return 0;
    }

当我将连接 BID 和 IDEX 的结果设置为结构 b 时发生错误的地方:

identityFieldO2M b;
b = result; // **error: no match for 'operator=' (operand types are 'identityFieldO2M' and 'int')**
memset(b.arr,0,sizeof(b.arr));

对于 BitFieldMember 模板,我在这里使用这个非常有用的模板: https://codereview.stackexchange.com/questions/54342/template-for-endianness-free-code-data-always-packed-as-big-endian

查看 BitFieldMember 模板的定义,这里是操作数 = 将值赋值到字段中,我怀疑这个问题可能出在哪里?

/* used to assign a value into the field */
inline self_t& operator=(unsigned m)
{
    uchar *arr = selfArray();
    m &= mask;
    unsigned wmask = ~(mask << (7 - (lastBit & 7)));
    m <<= (7 - (lastBit & 7));
    uchar *p = arr + lastBit / 8;
    int i = (lastBit & 7) + 1;
    (*p &= wmask) |= m;
    while (i < bitSize)
    {
        m >>= 8;
        wmask >>= 8;
        (*(--p) &= wmask) |= m;
        i += 8;
    }
    return *this;
}

根据您的位域定义,您需要使用 unsigned char[5] 并且它需要大端值(从遵循 link 到您获得此代码的位置)。正如您从编译器错误中看到的那样,您不能将其分配给 int 。一种选择是通过位移将 int 值复制到大端 b.arr 中。像这样的东西应该可以做到。

int result = 0x0828a0a0;
identityFieldO2M b;

b.arr[0] = (result >> 24) & 0xFF; // 0x08
b.arr[1] = (result >> 16) & 0xFF; // 0x28
b.arr[2] = (result >> 8) & 0xFF;  // 0xa0
b.arr[3] = result & 0xFF;         // 0xa0