IAR 编译器中的指针

pointers in the IAR compiler

长话短说,我使用 IAR EWARM 编译器在 C 中实现了这个。

uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = *src++;

最后一行导致总线故障。

uint8_t packet[2048];
uint32_t* src = (uint32_t*)&packet[9];
uint32_t var = 0xFE;
*src++;

现在没有总线故障。我可以在调试器中看到 src 指向我期望它指向的数据。增加它按预期工作,但尝试读取它会导致总线故障。

有什么帮助吗?

可能是您的 MCU 需要读取 32 位整数才能与 32 位对齐。

&packet[9] 肯定不是 32 位对齐的,这就是你出错的原因。

&packet[9] 可能未针对 uint32_t 正确对齐。在 ARM CPU 上看到 "Bus Error" 通常是对齐错误的标志。 See here 对齐的解释。

在第二个示例中,它可能通过优化 * 操作来避免总线故障,因为您从不使用结果。

请注意,即使您修复了此问题,代码仍会因违反严格的别名规则而导致未定义的行为。 (uint8_t 不能别名为 uint32_t)。一些编译器现在可能 "work correctly" 但代码可能会在未来的任何时候中断。

您的代码的安全等价物是:

uint8_t *src = &packet[9];
uint32_t var;
memcpy(&var, src, sizeof var);
src += sizeof var;

请注意,如果源数据被指定为具有特定的整数字节顺序(例如,您是从网络流中获取它,而不是之前通过相同方法保存的数据),那么您将需要使用一种方法读取独立于 uint32_t 表示的数据。 (换句话说,"endianness")。