9159金沙游艺场-奥门金沙游艺场-[欢迎您]

9159金沙游艺场为您呈现最新的面貌!,目前注册送体验金,欢迎您将成为影视娱乐行业新的风向标,是亚洲的优质娱乐先锋。

数组到结构体转换和联合体与位段结合中的大小

日期:2019-11-01编辑作者:前端

数组到结构体转换和联合体与位段结合中的大小端问题

移植驱动代码时发现工程中使用了如下形式的代码

typedef struct BlkTestTag{

uint16_tm_u1Var1;

uint8_t reserve[2];

uint32_tm_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的结果是我们想要的。
9159金沙游艺场 1

但是如果再大端MCU上执行的话结果就大不一样。

9159金沙游艺场 2

原因在于数组uint8_t test_array[8] = {0x01,0x02,0x00,0x00,0x05,0x06,0x07,0x08};

其数据在内存中是从低地址到高地址存放的,如下图

9159金沙游艺场 3

即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_tvar;

struct{

uint8_tbit0:1;

uint8_tbit1:1;

uint8_tbit2:1;

uint8_tbit3:1;

uint8_tbit4:1;

uint8_tbit5:1;

uint8_tbit6:1;

uint8_tbit7:1;

}pixels;

}UnTest;

在对联合体赋值后

unTest.var = 0x11; 二进制值为 00010001

上面的联合体定义就是为了判断某些位,所以我们希望的是赋值0x11后,位段的unTest.pixels.bit0和unTest.pixels.bit4的值应该为1 才对。
即我们希望的是名字能反应真正的bit值

在小端MCU中运行时的确是正确的。

9159金沙游艺场 4

但是在大端MCU中运行时结果如下图。

即联合体中 unTest.pixels.bit0的值反应的不再是真正的二进制中的bit0了

反而是unTest.pixels.bit7 反应的是真正的bit0.

即unTest.pixels.bit0- unTest.pixels.bit7 反应的真实值其实是bit7-bit0了

9159金沙游艺场 5

一般情况下 字节内的bit序 是不可见的,除非使用了上面的位段的情况下才会发现。
既然字节内bit序与大小端有段,那么为什么使用在使用 <>之类操作符时。都可以正常运行,这是芯片根据会自己更具自己大小端类型自动做相应的处理。

具体如下:
对于小端 如果 bit0 - bit7为 1000 1000
小端MCU认为这个值为 0x11 当做 << 操作后 二进制为0100 0100 小端MCU认为其值为0x22 ,的确是0x11的左移操作结果
可以看出这里的 << 实际操作是向 bit7方向移位了

对于大端 如果bit0-bit7为 1000 1000
9159金沙游艺场,大端MCU认为这个值为0x88 当做 << 操作后 二进制为 0001 0000 ,大端MCU认为其值为0x10, 也的确是 0x88左移溢出后的结果

但是这里的 << 实际操作是向bit0方向移位了

附上一段简单测试代码,在keil工程中 选择模拟器调试

9159金沙游艺场 6

然后勾选big endian的情况下 debug实例代码,然后打端点查看变量值,结果就是大端情形下的。不勾选 big endian 再debug跑一次就是小端情形下的

9159金沙游艺场 7

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;

/*测试大小端 <
unTest.pixels.bit0 = 1;
unTest.pixels.bit4 = 1;

unTest.var <<= 1;
*/
while(1);
return 0;
}

操作的>

移植驱动代码时发现工程中使用了如下形式的代码 typedef struct BlkTestTag{ uint16_tm_u1V...

本文由9159金沙游艺场-奥门金沙游艺场-[欢迎您]发布于前端,转载请注明出处:数组到结构体转换和联合体与位段结合中的大小

关键词:

模拟注册登录幸运抽奖全过程

初学Java5:模拟注册登录幸运抽奖全过程,java5幸运抽奖 刚刚好不容易写了很多,结果一不小心点错,关闭了,重点是...

详细>>

Gson解析相较于Json

Java--Gson剖析相较于Json,gsonjson -- Gson解析jar包:  链接: 密码:f9ig -- 官方Json剖判工具类: 1 package com.dragon.java.jsonw...

详细>>

CodeBlocks里面设置使用的终端

Ubuntu+CodeBlocks里面安装使用的终极,默许是xterm,呈现中文特别扯淡。。查了查资料换到了Gnome-Terminal,舒服多了~~...

详细>>

Linux的cgroup【9159金沙游艺场】

为什么要有cgroup Linux系统中经常有个需求就是希望能限制某个或者某些进程的分配资源。也就是能完成一组容器的概...

详细>>