首页 > 解决方案 > 定义具有特定对齐方式的自动变量的优雅方式

问题描述

我正在使用 ARM 编译器并有一个硬件外围设备(具有直接内存访问),它需要对传递给它的内存缓冲区进行特定对齐(32 字节对齐)。aligned当缓冲区是全局/静态的并且可以使用编译器支持的属性来定义时,这不是问题。只要需要在本地传递某个函数中定义的缓冲区,即具有自动存储类,就会出现问题。我试图做类似以下的事情:

typedef struct  __attribute__((aligned(32)))
{
    char bytes[32];
} aligned_t;

_Static_assert(sizeof(aligned_t)==32, "Bad size");

void foo(void)
{
    aligned_t alignedArray[NEEDED_SIZE/sizeof(aligned_t)];
    //.... use alignedArray
}

这很高兴地编译并在x86编译器上工作。但不是在armcc,这是抱怨:

警告:#1041-D:自动对象的对齐方式不得大于 8

所以这种方法行不通。还有一个,我认为很丑:

void foo(void)
{
    char unalignedBuffer[NEEDED_SIZE + 32 - 1];
    char pAlignedBuffer = ALIGN_UP_32(unalignedBuffer);
    //.... use pAlignedBuffer
}

虽然ALIGN_UP_32是一个宏,用于返回其中的第一个对齐地址unalignedBuffer(我猜这里的实现细节并不重要)。

正如我所说,我不喜欢这种方法,想知道是否有更优雅的方法来实现同样的效果?

标签: carmmemory-alignmentarmcc

解决方案


我正在使用 ARM 编译器

您是否也尝试过最近的 GCC(可能配置为交叉编译器),例如 2018 年 11 月的 GCC 8?

ARM ABI 不保证堆栈指针(可能)与 32 字节对齐。

因此,任何自动变量都不会像您想要的那样对齐。

您可以避免它们(并系统地使用适当对齐的堆内存区域)。或者你可以分配比需要更多的东西并对其进行指针运算。

我觉得你char* pAlignedBuffer = ALIGN_UP_32(unalignedBuffer);的方法很好,我相信优化编译器会生成非常有效的代码。

我不喜欢这种方法,想知道是否有更优雅的方法来实现同样的效果?

我相信你的方法很好,任何其他方式都是等效的。

PS。另一种方法可能是修补您的 GCC 编译器(可能使用插件)以更改堆栈指针的默认对齐方式(因此有效地更改您的ABI调用约定)。这将花费您数周(或数月)的努力。


推荐阅读