如何在GCC C中获得对齐的打包结构数组?

时间:2015-11-09 17:04:21

标签: c gcc struct packed

在GCC C中,我如何获得一个打包结构数组,其中数组中的每个条目都是对齐的?

(FWIW,这是在PIC32上,使用MIPS4000架构)。

我有这个(简化):

typedef struct
{
    short           read;               // next buffer to read
    short           write;              // next buffer to write
    short           count;              // number of packets stored in q
    short           buffers;            // number of buffers allocated in q
    RADIO_PACKET q[RADIO_RX_PACKET_BUFFERS];
} RADIO_PACKET_QUEUE;

RADIO_PACKET在内部打包。

然后我有RADIO_PACKET_QUEUE,这是RADIO_PACKETs的队列:

RADIO_PACKET_QUEUE rpq;
int foo = *(int*) &(rpq.q[1]);

我希望数组q []中的每个RADIO_PACKET都以对齐的地址(模4地址)开始。

但是现在GCC没有对齐它们,所以当我尝试将q [n]读作一个单词时,我得到地址异常。例如,这给出了一个例外:

TextView

也许这是因为我将RADIO_PACKET声明为打包的方式。

我希望每个RADIO_PACKET在内部保持打包状态,但是希望GCC在每个数组元素之后根据需要添加填充,以便每个RADIO_PACKET从对齐的地址开始。

我该怎么做?

3 个答案:

答案 0 :(得分:3)

由于您指定使用GCC,因此您应该查看类型属性。特别是,如果您希望{4}在4字节(或更宽)边界上对齐,那么您将在类型上使用RADIO_PACKET。应用于__attribute__((aligned (4)))时,它描述了整个struct实例的对齐方式,而不是(直接)任何单个成员的对齐方式,因此可以将其与属性{{1}一起使用}:

struct

packed属性可以防止结构元素之间的填充,但会阻止结构表示中的尾部填充,这与确保数组的每个元素所需的对齐所必需的完全相同指定类型的。那么你不应该在typedef struct __attribute__((aligned(4), packed)) { uint8_t frameLength; unsigned frameType :3; uint8_t payloadBytes; uint8_t payload[RADIO_RX_PAYLOAD_WORST]; } RADIO_PACKET; 的声明中做任何特别的事情。

这比你提出的替代方案更清晰,更清晰,但它是GCC特有的。由于你已经是GCC特定的,我不认为这是一个问题。

答案 1 :(得分:2)

您可以将打包的结构包裹在另一个未对齐的结构中。然后你从这个未对齐的结构做数组。

解决方案2可以是,在打包结构的末尾添加虚拟成员char []。在这种情况下,您需要以某种方式计算它,可能是手动计算。

我还建议您重新排列结构,先放置较长的成员并将uint8_t成员放在最后(假设您有16/32位成员而不进行某些硬件映射)。

答案 2 :(得分:1)

我想我已根据问题评论中@Nick的暗示解决了这个问题。

我在RADIO_PACKET附近添加了一个RADIO_PACKET_ALIGNED包装器。这包括计算填充。

然后我在RADIO_PACKET_QUEUE结构中用RADIO_PACKET替换RADIO_PACKET_ALIGNED。

似乎工作:

typedef struct
{
    RADIO_PACKET packet;
    uint8_t padding[3 - (sizeof(RADIO_PACKET) + 3) % 4];
} RADIO_PACKET_ALIGNED;

typedef struct
{
    short           read;               // next buffer to read
    short           write;              // next buffer to write
    short           count;              // number of packets stored in q
    short           buffers;            // number of buffers allocated in q
    RADIO_PACKET_ALIGNED q[RADIO_RX_PACKET_BUFFERS];
} RADIO_PACKET_QUEUE;

感谢所有评论者!

编辑:包装器的更便携版本将使用:

uint8_t padding[(sizeof(int) - 1) - (sizeof(RADIO_PACKET) + (sizeof(int) - 1)) % sizeof(int)];