我有两个位域:(1)一个用于处理帧(标题),(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;
};
我需要首先处理第一个位域,然后从那里我将这个位域的两个成员组合起来,然后将它们的组合输出运行到另一个位域以确定子帧。然而,我遇到的问题是,当我使用按位函数组合两个位域时,我无法将此数据传回位域。
我想我正在做一些“呃”错的事,但我无法弄清楚这一点。以下是我的实施:
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的结果设置为struct 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]
并且它期望大端值(从链接到您获得此代码的位置)。您从编译器错误中看到的不能将它分配给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