我正在为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
。
我的cflags是:
-mcpu=arm7tdmi -Os -gdwarf-2 -mthumb-interwork -fomit-frame-pointer -Wall -Wpadded -Wstrict-prototypes -fstrict-aliasing -fverbose-asm -Wa
问题1:如何使用arm-none-eabi-gcc设置默认数据对齐方式
我知道
static uint8 cTelBuf[TTX_TEL_LENGTH] __attribute__((aligned(4)));
将解决这种情况下的问题,但我想一般设置对齐方式。 IAR编译器是如何做到这一点的?
问题 2:有没有办法避免这个问题(无需复制)?
我的意思是:如果我想要TTXSpecial_t
怎么办?结构从 cTelBuf+1
开始。
一种解决方案可能是 memcpy cTelBuf+1
分配给 TTXSpecial_t
struct,但是如何在不分配额外内存的情况下做到这一点?
最佳答案
你的问题是你有类型但不使用它们。编译器知道 TTXSpecial_t
包含需要 4 字节对齐的 32 位值。问题是您将 cTelBuf 声明为字节数组,编译器只能说字节访问不需要对齐。
因此,我建议您将字节数组声明为实际类型 TTXSpecial_t
(并将其强制转换为对 uint8 的字节访问),或者通过将其声明为 union 使其成为组合数据类型(即,作为重叠的 TTXSpecial_t
和 unit8
数组)。
据我所知,gcc 中没有通用选项来更改变量的默认对齐方式(某些架构有特殊的 -malign 开关,但我认为对于 arm 来说不可用),快速浏览一下 IAR 文档就会发现,IAR编译器的行为方式相同。这意味着他会在 4 字节边界对齐你的结构类型的变量,但声明的字节数组只会是 1 字节对齐 - 看来你很幸运,使用 IAR 编译器的代码从来没有出现问题 - 你应该修复尽快,因为它也可能发生在那里。
关于gcc - 如何使用arm gcc设置变量的默认对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17881720/