我正在开发一个arm7tdmi目标的应用程序。 我以前用IAR编译代码,但现在我切换到arm-none-eabi-gcc,我有以下问题。
typedef struct
{
uint32 nNumber;
uint32 nPara1;
uint32 nPara2;
uint32 nPara3;
uint32 nPara4;
uint32 nPara5;
uint32 nParax[122];
} TTXSpecial_t;
static uint8 cTelBuf[TTX_TEL_LENGTH];
例如,cTelBuf
放置在0x4000000A
&(((TTXSpecial_t *)cTelBuf)->nNumber)
返回相同的地址,到目前为止一切正常。
<小时/>cTelBuf
已填满,((TTXSpecial_t *)cTelBuf)->nNumber
应为0x87654321
。
内存转储显示:
0x40000000: 00 00 04 00 00 02 0C 00 00 02 21 43 65 87 00 00
0x40000010: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
<小时/> 问题是每当我阅读
(TTXSpecial_t *)cTelBuf)->nNumber
时,该值将为0x2004321
。
因此,您可以看到读取是在地址0x40000008
而非0x4000000A
完成的。
-mcpu=arm7tdmi -Os -gdwarf-2 -mthumb-interwork -fomit-frame-pointer -Wall -Wpadded -Wstrict-prototypes -fstrict-aliasing -fverbose-asm -Wa
static uint8 cTelBuf[TTX_TEL_LENGTH] __attribute__((aligned(4)));
将解决问题,但我想设置一般的对齐方式。 IAR编译器是如何做到的?
问题2:有没有办法避免这个问题(没有复制)?
我的意思是:如果我希望TTXSpecial_t
结构从cTelBuf+1
开始,该怎么办?
一种解决方案可能是将cTelBuf+1
memcpy到已分配的TTXSpecial_t
结构,但如何在不分配额外内存的情况下进行操作?
答案 0 :(得分:3)
你的问题是你有类型而且不使用它们。编译器知道TTXSpecial_t
包含需要4字节对齐的32位值。问题是您将cTelBuf声明为字节数组,其中编译器只能说字节访问不需要对齐。
所以我建议你将你的字节数组声明为你的实际类型TTXSpecial_t
(并将其转换为对你的uint8的字节访问),或者通过将它声明为union来使其成为组合数据类型(即您重叠的TTXSpecial_t
和unit8
数组。
Afaik gcc中没有通用选项可以更改变量的默认对齐方式(某些架构有特殊的-malign开关,但我手臂上的东西都不可用),快速浏览IAR文档说,IAR编译器的行为方式相同。这意味着他将你的结构类型的变量对齐为4字节边界,但声明的字节数组只能对齐1个字节 - 看起来你很幸运,你从来没有使用IAR编译器的代码问题 - 你应该修复它尽可能地发生在那里。