gcc - 如何使用arm gcc设置变量的默认对齐方式

标签 gcc arm default memory-alignment

我正在为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_tunit8 数组)。

据我所知,gcc 中没有通用选项来更改变量的默认对齐方式(某些架构有特殊的 -malign 开关,但我认为对于 arm 来说不可用),快速浏览一下 IAR 文档就会发现,IAR编译器的行为方式相同。这意味着他会在 4 字节边界对齐你的结构类型的变量,但声明的字节数组只会是 1 字节对齐 - 看来你很幸运,使用 IAR 编译器的代码从来没有出现问题 - 你应该修复尽快,因为它也可能发生在那里。

关于gcc - 如何使用arm gcc设置变量的默认对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17881720/

相关文章:

c++ - 隐藏成员函数模板 - 哪个编译器是正确的?

gcc - 在 Windows 中静态链接 GTK+ 库

c++ - GCC 根据数组索引值生成不同的代码

ios - iOS 上编译成功但执行汇编 MRC 指令失败?

c++ - 我定义了一个非拷贝构造函数;复制构造函数是否仍会被隐式定义?

linux - x86_64 机器的 GCC 内联汇编的汇编程序错误(at&t 语法)

c - 为什么 GCC -Ofast 使程序出错,但仅在它打印两次结果时才出错?

linux - 在 x86 上为 ARM 构建 opencv 应用程序

mysql - 如何在 MySQL 中将现有列更改为默认插入时的当前时间?

Angular 2+ 设置标准表单字段外观值