3

GCC C では、配列内の各エントリが整列されている、パックされた構造体の配列を取得するにはどうすればよいですか?

(FWIW、これは MIPS4000 アーキテクチャを使用する PIC32 上にあります)。

私はこれを持っています(簡略化):

  typedef struct __attribute__((packed))
  {
      uint8_t     frameLength; 
      unsigned    frameType       :3;
      uint8_t     payloadBytes;  
      uint8_t     payload[RADIO_RX_PAYLOAD_WORST];
  } RADIO_PACKET;

RADIO_PACKET は内部でパックされます。

次に、RADIO_PACKET のキューである RADIO_PACKET_QUEUE があります。

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;

配列 q[] 内の各 RADIO_PACKET をアラインされたアドレス (モジュロ 4 アドレス) で開始する必要があります。

しかし、現在 GCC はそれらを整列していないため、q[n] を単語として読み取ろうとするとアドレス例外が発生します。たとえば、これは例外を与えます:

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

おそらくこれは、RADIO_PACKET をパックとして宣言した方法が原因です。

各 RADIO_PACKET を内部的にパックしたままにしたいが、GCC が必要に応じて各配列要素の後にパディングを追加して、各 RADIO_PACKET がアラインされたアドレスから開始するようにしたい。

これどうやってするの?

4

3 に答える 3

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)];
于 2015-11-09T17:51:28.310 に答える