我在32位嵌入式系统上转换和修改指针时遇到了一个奇怪的问题(具体地说,是运行contiki OS的redbee econotag)。
uint32_t array[2];
array[0] = 0x76543210;
array[1] = 0xfedcba98;
uint8_t* point = ((uint8_t*)array)+1;
printf("%08x \n", *(uint32_t*)point );我的计算机上的输出:
98765432嵌入式设备上的输出:
10765432我的电脑按照我的预期运行,然而,当嵌入式设备到达单词的末尾时,它似乎会绕来绕去。这一切为什么要发生?
发布于 2012-12-26 10:14:47
您的目标"redbee econotag“被声明为具有ARMv4架构的ARM7。ARMv4不像ARMv7或英特尔机那样提供非对齐的内存访问。
引用ARM's documentation
On ARMv4和ARMv5架构,以及ARMv6架构,这取决于它是如何配置的,在访问内存中未对齐的数据时需要小心,以免返回意外结果。例如,当使用常规指针读取C或C++源代码中的一个字时,ARM编译器生成使用LDR指令读取该字的汇编语言代码。当地址是四的倍数时,这是预期的,例如,如果它位于字边界上。但是,如果地址不是4的倍数,则将返回旋转结果,而不是执行真正的未对齐字加载。通常,这种轮换不是程序员期望的。
发布于 2012-12-26 00:53:12
使用这段代码,您可以打破严格的别名规则:具有uint32_t类型的左值表达式可以访问point指向的对象。
C11 (n1570),§6.5 Expression
对象的存储值只能由具有以下类型之一的左值表达式访问:
-与对象的有效类型兼容的类型,
-与对象的有效类型兼容的类型的合格版本,
-与对象的有效类型相对应的有符号或无符号类型的类型,
-作为与对象的有效类型的限定版本相对应的有符号或无符号类型的类型,
-在其成员中包含上述类型之一的聚合或联合类型(递归地包含子聚合或包含的联合的成员),或者
-a字符类型。
这会导致未定义的行为,因此任何事情都可能发生。
C11 (n1570),§4. Conformance
如果出现在约束或运行约束之外‘’应当‘’或‘’不得‘要求被违反,则该行为受到fined的约束。
发布于 2012-12-26 05:34:03
由于+1,您需要对32位值进行未对齐的访问,即地址不是4的倍数。
x86独立于对齐工作,因为它的根源可以一直追溯到8位机器(可能性能稍差)。
ARM需要对齐(与许多其他处理器一样),因此32位值应该放在四个字节的倍数的地址上。如果不是这样,可能会发生各种不好的事情(错误的值,错误)。对于数组,编译器负责这一点,但当您显式地转换指针时,您会强制它违反对齐。
https://stackoverflow.com/questions/14032434
复制相似问题