4

我有变量uint16 value,我想将它复制到uint8_t buffer[3]. 是否可以这样做(小端):

*buffer=*(uint8_t *)&value;

代替:

buffer[0] = highByte(value);
buffer[1] = lowByte(value);

由于此替换导致 stm32f7 I2C 无法正常工作。有正确的铸造吗?

4

3 回答 3

6

STM32 是小端的,所以你首先得到最低有效字节:

uint8_t* ptr = (uint8_t*)&value;
uint8_t low  = ptr[0];
uint8_t high = ptr[1];

像这样进行强制转换和取消引用仅适用于字符类型。上面的代码假设uint8_t是字符类型,很可能是这种情况(在 gcc 和其他主流编译器上)。

有关更多信息,请参阅什么是 CPU 字节序?

编辑:

如果您只是想将 16 位数字复制到字节数组中,正确的解决方案是:

memcpy(buffer, &value, sizeof(uint16_t)).

我们不能这样做*(uint16_t*) buffer=value;,因为它会调用未定义的行为。buffer可能未对齐,这也是严格的混叠违规。这就是为什么我在上面强调“这仅适用于字符类型”的原因。

于 2021-12-14T07:09:34.843 回答
2

有正确的铸造吗?

*buffer = <expression>

将永远且只会写信给buffer[0],而永远不会写给buffer[1].

你可以做的一件事——但我强烈建议你不要这样做:

uint16_t *ptr = (uint16_t*)buffer; // Ugh, danger
*ptr = value;

如果您在具有不同字节序的机器上运行它,这将是有问题的。而且很有可能还有其他原因不这样做。一旦你问自己是否可以通过强制转换解决问题,你真的应该退后一步。这是我写过的两个答案:

https://stackoverflow.com/a/62563330/6699433

https://stackoverflow.com/a/63773195/6699433

于 2021-12-14T07:12:31.480 回答
0

假设要解决@Lundin 提到的与高端和低端相关的问题,并且取消引用 uint8_t 仅授予对它的第一个数组元素的访问权限,我只通过一次强制转换就达到了这个解决方案:

*(uint16_t*) buffer=value;

哪个是简化版:

uint16_t* p;
p= buffer;
*p=value;
于 2021-12-14T09:38:25.710 回答