Baa*_*arn 7 c embedded x86 arm contiki
在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 );
Run Code Online (Sandbox Code Playgroud)
在我的电脑上输出:
98765432
Run Code Online (Sandbox Code Playgroud)
嵌入式设备上的输出:
10765432
Run Code Online (Sandbox Code Playgroud)
我的计算机表现得像我期望的那样,但嵌入式设备似乎在它到达单词结尾时回滚.为什么会这样?
md5*_*md5 13
使用此代码,您可以破坏严格别名规则:指向的对象由point具有uint32_t类型的左值表达式访问.
C11(n1570),§6.5表达式
对象的存储值只能由具有以下类型之一的左值表达式访问:
- 与对象的有效类型兼容的类型,
- 与之兼容的类型的限定版本对象的有效类型,
- 对应于对象的有效类型的有符号或无符号类型的类型,
- 对应于对象的有效类型的限定版本的有符号或无符号类型,
-聚合或联合类型,包括其成员中的上述类型之一(包括递归地,子聚合或包含联合的成员),或
- 字符类型.
这会导致未定义的行为,因此任何事情都可能发生.
C11(n1570),§4.一致性
如果违反约束或运行时约束之外的"应该"或"不应该"要求,则行为未定义.
aus*_*len 13
您的目标"redbee econotag"被声明为具有ARMv4架构的ARM7.ARMv4不提供像ARMv7或intel机器那样的未对齐内存访问.
引用ARM的文档:
在ARMv4和ARMv5体系结构以及ARMv6体系结构(取决于其配置方式)上,在访问内存中的未对齐数据时需要小心,以免返回意外结果.例如,当传统指针用于读取C或C++源代码中的单词时,ARM编译器生成使用LDR指令读取单词的汇编语言代码.当地址是四的倍数时,这可以正常工作,例如,如果它位于单词边界上.但是,如果地址不是4的倍数,则LDR返回旋转结果,而不是执行真正的未对齐字加载.通常,这种旋转不是程序员所期望的.
printf("%08x \n", *(uint32_t*)point );
Run Code Online (Sandbox Code Playgroud)
*此语句中的表达式调用未定义的行为:它违反了别名规则,可能会执行未对齐的访问.
由于+1您对32位值进行了未对齐访问,即地址不是4的倍数.
x86独立于对齐工作,因为它的根源一直回到8位机器(可能性能稍差).
ARM需要对齐(与许多其他处理器一样),因此应将32位值放在四个字节的倍数的地址上.如果不是这种情况可能会发生各种不好的事情(错误的值,错误).对于数组,编译器会处理这个问题,但是当您显式地转换指针时,会强制它违反对齐.
| 归档时间: |
|
| 查看次数: |
1465 次 |
| 最近记录: |