分类: C/C++
2016-08-23 20:15:37
移植驱动代码时发现工程中使用了如下形式的代码
typedef struct BlkTestTag{
uint16_t m_u1Var1;
uint8_t reserve[2];
uint32_t m_u4Var2;
}BlkTest;
uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
pblkTest = (BlkTest *)test_array;
u2Var1 = pblkTest->m_u1Var1;
u4Var2 = pblkTest->m_u4Var2;
本意是为了将结构体的值以数组常量形式给出。
让var1 = 0x0201; var2 = 0x08070605
再将这些代码移植到另一款MCU时发现工作不正常。之后发现移植的这款MCU是大端的,而我们之前的使用的MCU都是小端的。于是定位上上面的数组赋值代码。
在小端MCU下会按我们想要的结果来赋值,如下图。Var1和var2的结果是我们想要的。
但是如果再大端MCU上执行的话结果就大不一样。
原因在于数组uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
其数据在内存中是从低地址到高地址存放的,如下图
即0x20000000地址处为0x01, 0x20000000地址处为0x02……
所以直接将数组名转换成结构体指针后,在访问m_u1Var1成员时,该成员为2字节无符号整型,所以他会将0x20000000 和0x20000001 地址处的两个值当做 m_u1Var1
所以如果是小端MCU 低地址0x20000000的值0x01会被解释为低字节
高地址0x20000001的值0x02会被解释为高字节
于是值就是 0x0201
如果是大端MCU 低地址0x20000000的值0x01会被解释为高字节
高地址0x20000001的值0x02会被解释为低字节
于是值就是 0x0102
这个数组到结构体的转换问题,在知道了大小端后问题定位还比较容易。
另一个关于联合体的问题就有点偏,即字节内的bit序在大小端MCU上也是不同的。
工程中存在如下代码
typedef union UnTestTag{
uint8_t var;
struct{
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
}pixels;
}UnTest;
在对联合体赋值后
unTest.var = 0x11; 二进制值为 00010001
上面的联合体定义就是为了判断某些位,所以我们希望的是赋值0x11后, 位段的 unTest.pixels.bit0和 unTest.pixels.bit4的值应该为1 才对。
即我们希望的是名字能反应真正的bit值
在小端MCU中运行时的确是正确的。
但是在大端MCU中运行时 结果如下图。
即 联合体中 unTest.pixels.bit0的值反应的不再是真正的二进制中的bit0了
反而是unTest.pixels.bit7 反应的是真正的bit0.
即unTest.pixels.bit0- unTest.pixels.bit7 反应的真实值其实是bit7-bit0了
但是这里的 << 实际操作是向bit0方向移位了
附上一段简单测试代码,在keil工程中 选择模拟器调试
然后勾选big endian的情况下 debug实例代码,然后打端点查看变量值,结果就是大端情形下的。不勾选 big endian 再debug跑一次就是小端情形下的
typedef struct BlkTestTag{
uint16_t m_u1Var1;
uint8_t reserve[2];
uint32_t m_u4Var2;
}BlkTest;
uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};
typedef union UnTestTag{
uint8_t var;
struct{
uint8_t bit0:1;
uint8_t bit1:1;
uint8_t bit2:1;
uint8_t bit3:1;
uint8_t bit4:1;
uint8_t bit5:1;
uint8_t bit6:1;
uint8_t bit7:1;
}pixels;
}UnTest;
BlkTest *pblkTest;
uint16_t u2Var1;
uint32_t u4Var2;
UnTest unTest;
int main(void){
pblkTest = (BlkTest *)test_array;
u2Var1 = pblkTest->m_u1Var1;
u4Var2 = pblkTest->m_u4Var2;
unTest.var = 0x11;