- 本人在做项目过程中需要在ARM对从FPGA读取到的数据进行处理,在实际过程中产生了一些问题,在思考了后记录在此。
1 大小端模式
- 大小端指数据在内存中的存储方式。小端指数据的高字节保存在内存的高地址处,低字节保存在内存的低地址处。大端模式则正好相反。ARM和x86的CPU一般情况下都为小端模式。
- 对于值unsigned int value = 0x12345678,在内存中的存储方式如下。
内存地址 | 小端模式存放内容 | 大端模式存放内容 |
---|---|---|
0x00004000 | 0x78 | 0x12 |
0x00004001 | 0x56 | 0x34 |
0x00004002 | 0x34 | 0x56 |
0x00004003 | 0x12 | 0x78 |
2 栈上的数据存储
- 局部变量在栈上存储,而栈由高地址向低地址方向增长。因此我们创建三个局部变量时,内存区如下图所示。我们由下图可以看到,在x86上,低字节存储在低地址,而栈由高地址向下增长。
unsigned int a = 0x12345678;
unsigned short b = 0x1234;
unsigned char c = 0x12;
- 结构体在栈上的存储时,在结构体中靠前面的成员存储在低地址处。如下面这个结构体,inta成员存储在低地址处,charc成员存储在高地址处。
#pragma pack(1)
typedef struct _ppp
{
unsigned int inta;
unsigned short shortb;
unsigned char charc;
}structp;
#pragma pack()
struct structp ppppp;
ppppp.inta = a;
ppppp.shortb = b;
ppppp.charc = c;
- 我们可以看到,结构体变量ppppp存储在0x0065FE4A地址处,inta成员存储在低地址处,charc成员存储在高地址处。
3 Qt中的QByteArray与结构体转换的问题
- 在Qt中,我经常将变量或结构体转换成QByteArray类型,然后进行传递。
QByteArray ba;
unsigned int a = 0x12345678;
unsigned short b = 0x1234;
unsigned char c = 0x12;
ba.append(QByteArray((const char*)&b, sizeof(unsigned short)));
ba.append(QByteArray((const char*)&c, sizeof(unsigned char)));
ba.append(QByteArray((const char*)&a, sizeof(unsigned int)));
- 变量ba在内存中的布局如下图所示,因此我可以用下面这种方式拆分QByteArray类型。
QByteArray bab = ba.mid(0, 2);
QByteArray bac = ba.mid(2, 1);
QByteArrat baa = ba.mid(3, 4);
unsigned short* pbab = (unsigned short*)bab.data(); //0x1234
unsigned char* pbac = (unsigned char*)bac.data(); //0x12
unsigned int* pbaa = (unsigned int*)baa.data(); //0x12345678
- 对于结构体看似这种方法也是正确的。变量structpp在内存中存储在0x0065FE39处,变量ba存储在0x00977280处。
QByteArray ba;
struct structp structpp;
structpp.inta = 0x12345678;
structpp.shortb = 0x1234;
structpp.charc = 0x12;
ba.append((const char*)&structpp, sizeof(structp));
structp* pstructp = (structp*)ba.data();
- 但如果