数组的内存对齐

10

在Cell处理器上,我在DMA传输中对齐内存遇到了问题。我需要一个地址的最后4位为0。

我有4个unsigned int数组,每个元素都必须在内存中对齐,以使其(十六进制)地址以零结尾。

例如:

int main()
{
    size_t i;

    static unsigned int a[2] __attribute__ ((aligned (16)));
    static unsigned int b[2] __attribute__ ((aligned (16)));
    static unsigned int c[2] __attribute__ ((aligned (16)));
    static unsigned int d[2] __attribute__ ((aligned (16)));

    for (i = 0; i < 2; ++i) {
        printf("a[%u] = %p\n", &a[i]);
        printf("b[%u] = %p\n", &b[i]);
        printf("c[%u] = %p\n", &c[i]);
        printf("d[%u] = %p\n", &d[i]);
    }

    return 0;
}

输出:

a[0] = 0x10010b60
b[0] = 0x10010b50
c[0] = 0x10010b40
d[0] = 0x10010b30
a[1] = 0x10010b64
b[1] = 0x10010b54
c[1] = 0x10010b44
d[1] = 0x10010b34

问题在于每个数组的第二个元素似乎没有16位对齐(它们的地址以4结尾)。

我需要地址看起来像这样:

a[0] = 0xXXXXXXX0
b[0] = 0xXXXXXXX0
c[0] = 0xXXXXXXX0
d[0] = 0xXXXXXXX0
a[1] = 0xXXXXXXX0
b[1] = 0xXXXXXXX0
c[1] = 0xXXXXXXX0
d[1] = 0xXXXXXXX0

2
(aligned (16)) 表示在 16 字节边界上对齐。 - JAB
你想要的地址以0结尾。这意味着你需要16字节对齐,而不是16位对齐。只是一个更正。 - talekeDskobeDa
3个回答

12

alignment属性指定的是变量或结构体字段的对齐方式,而不是单个数组元素的对齐方式。详情请参见指定变量属性常用变量属性

如果您总是希望将两个整数对齐在一起,则可以定义一个结构体。

struct dma_transfer {
    unsigned int e0 __attribute__ ((aligned (16)));
    unsigned int e1 __attribute__ ((aligned (16)));
};

这将把元素对齐到16字节边界上。

int main(int argc, char **argv)
{
    static struct dma_transfer a;
    static unsigned int b[2];

    printf("a.e0 = %p\n", &a.e0);
    printf("a.e1 = %p\n", &a.e1);
    printf("b[0] = %p\n", &b[0]);
    printf("b[1] = %p\n", &b[1]);

    return 0;
}

例如,给出

a.e0 = 0x601060
a.e1 = 0x601070
b[0] = 0x601080
b[1] = 0x601084

但这也意味着,在两个整数值之间存在空洞。在32位系统上,您将拥有

| int 4 bytes | hole 12 bytes |
| int 4 bytes | hole 12 bytes |


6
如果arr是一个32位元素的数组,并且arr[0]的地址为0xXXXXXXX0,那么arr[1]的地址必定是0xXXXXXXX4
为了您的目的,您需要使用16字节元素的数组:
typedef struct
{
    unsigned int x;
    unsigned char reserved[16-sizeof(unsigned int)];
}
element_t;

static element_t a[2] __attribute__ ((aligned (16)));
static element_t b[2] __attribute__ ((aligned (16)));
static element_t c[2] __attribute__ ((aligned (16)));
static element_t d[2] __attribute__ ((aligned (16)));

或者,您可以完全避免使用数组。

相反,使用普通变量,并告诉编译器将它们对齐到16字节:

static unsigned int a0 __attribute__ ((aligned (16)));
static unsigned int a1 __attribute__ ((aligned (16)));
static unsigned int b0 __attribute__ ((aligned (16)));
static unsigned int b1 __attribute__ ((aligned (16)));
static unsigned int c0 __attribute__ ((aligned (16)));
static unsigned int c1 __attribute__ ((aligned (16)));
static unsigned int d0 __attribute__ ((aligned (16)));
static unsigned int d1 __attribute__ ((aligned (16)));

4

我真的不认为你能做到那一点...你试图让编译器在“unsigned int”内部注入额外的填充来进行对齐。但是没有空间可以这样做,因为“unsigned int”中的所有位都已经用于整数本身。

我认为解决方案是将整数包装在一个结构体中,因为这样你就可以在结构体上使用“__attribute__(())”魔术,并创建一个该结构体的数组。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接