嵌入式系统上的指针,32位变量的字节指针通过指针转换

时间:2014-09-23 12:03:15

标签: c pointers casting embedded byte

我必须读出uint32_t变量的字节,我已经看到了这种情况 我的一位同事的实施。我的问题是,如果该代码示例的行为在"几乎所有" 32位 微控制器。是否可以在每个32位微控制器上工作,还是我依赖​​的平台特定行为? P.S。:在这个例子中不应该考虑系统的字节序。

uint8_t     byte0=0;
uint8_t     byte1=0;
uint8_t     byte2=0;
uint8_t     byte3=0;
uint8_t     *byte_pointer;  //byte_pointer
uint32_t    *bridge_pointer;//pointer_bridge between 32bit and 8 bit variable
uint32_t    var=0x00010203;

bridge_pointer=&var;    //bridge_pointer point to var
byte_pointer=(uint8_t *)(bridge_pointer);   //let the byte_pointer point to bridge_pointer

byte0=*(byte_pointer+0);    //saves byte 0
byte1=*(byte_pointer+1);    //saves byte 1
byte2=*(byte_pointer+2);    //saves byte 2
byte3=*(byte_pointer+3);    //saves byte 3

先谢谢

3 个答案:

答案 0 :(得分:4)

您应该将byte_pointer声明为unsigned char*,如果您在小端接受不同的输出,那么您的示例将起作用。这是一个解决方案,它不依赖于endianess

uint8_t byte0 = var;
uint8_t byte1 = var>>8;
uint8_t byte2 = var>>16;
uint8_t byte3 = var>>24;

byte0将成为LSB

答案 1 :(得分:3)

byte0=*(byte_pointer+0);    //saves byte 0

此行(以及以下行)违反严格别名。声明为uint32_t的对象是通过类型uint8_t的左值访问的;应使用unsigned char而不是uint8_t,因为允许字符类型的左值访问不同类型的对象(如果存在uint8_t,则其行为与unsigned char相同尽管有更宽松的锯齿规则)。

unsigned char *byte_pointer = (unsigned char *)(bridge_pointer);
uint8_t byte0 = *(byte_pointer+0);
    // byte0 can still be uin8_t, the access to var is important for aliasing

comment中所述,byte_pointer[0]相当于*(byte_pointer+0),更为常见。

通过此更改,代码具有明确定义的行为。 (并且可以移植到具有uint32_tuint8_t的实现,虽然字节顺序可能导致不同的结果,如问题中所述。)

严格混叠的相关标准部件为6.5 p6 / 7.

答案 2 :(得分:1)

实际上,除了字节序问题外,代码都是可移植的。通过uint8_t指针访问uint32_t的一部分将始终在标准之外的现实世界中工作。

Whether uint8_t is considered a character type or not is debated,但这个讨论仅仅是学术界的兴趣。 (如果要将其视为字符类型,则不会在标准6.5 / 7中使用中断别名规则。)实际上,uint32_t将不包含任何填充位或标准允许的其他理论无意义。

为了避免语句问题,我建议重新编写代码以使用位移,这在@ mch的答案中已被证明。