从uchar *转换为uint *会产生不可预测的结果

时间:2019-01-14 03:18:42

标签: c arm

我正在用C99(具有一些不同的类型定义,例如uint32而不是uint32_t)编译此代码,以用于旧的手臂体系结构。

    uint32 x2 = *((uint32 *) &data[t]);
    uint32 x3;
    memcpy(&x3, &data[t], 4);
    printf("%d %d %d %d %d %d", x2, x3, data[t], data[t + 1], data[t + 2], data[t + 3]);

(数据为uchar *,且长度> t + 4)

但是令人惊讶的输出是这样的:

-268435454 2 2 0 0 0

此转换有什么问题?

3 个答案:

答案 0 :(得分:4)

x2行导致未定义的行为。首先,data[t]可能没有32位对齐方式,其次,从该位置读取32位值可能是严格的别名冲突。

只需删除该行并使用x3版本。

答案 1 :(得分:2)

如其余答案所述,问题来自unaligned access。虽然x64或x86绝对支持不对齐访问,但是您不能说ARM完全(不支持/-)支持不对齐访问,因为它取决于ARM版本。 有三种可能性:

  • 在ARMv5(包括)之前。 ARM不支持uint32 x2 = *((uint32 *) &data[t]);所做的未对齐访问(从LDR来看,32bit变量的四个字节中的三个未对齐为4,只有一个已对齐),因此结果是不确定的(因此出错)。鉴于此,问题必须由软件解决(在ARM上,__packed对于未对齐的指针或结构很有用)。
  • 在ARMv7(包括)之后,它们确实允许未对齐的访问*,因此代码应该有效,没有错误(但是,性能是完全不同的主题,而且我敢肯定,与对齐对32位的访问相比,它会更慢,但该主题应有自己的条目)。
  • ARMv6。通常,ARM可以使事情变得更有趣,并且对齐方式不会有所不同。他们在这里添加了a bit,以便选择您喜欢的方式(ARMv5或ARMv7)。

    考虑“用于老式的手臂体系结构” 注释,您的案例看起来像第一个案例,但是如果您包括汇编代码和体系结构,那将是一个完整的答案。

*某些说明会因无法支持而失败(例如STM

答案 2 :(得分:-1)

您在这里遇到几个问题。不要使用指针修剪,而要使用联合。

您的printf格式也是错误的。您应该使用%u而不是%d