組み込みの世界では、固定長のバッファを介して渡されるデータ構造がよくあります。これらは、次のようなものを使用して比較的簡単に処理できます。
#define TOTAL_BUFFER_LENGTH 4096
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
};
static_assert(sizeof(struct overlay) <= TOTAL_BUFFER_LENGTH);
struct overlay* overlay = malloc(TOTAL_BUFFER_LENGTH);
つまり、データ構造をオーバーレイとして使用して、現在使用されているバッファーの部分に簡単にアクセスできるようにします。
ただし、バッファの最後の数バイトを使用してチェックサムなどを保存するバッファ形式もいくつかあります。現在、次のような構造を使用しています。
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
sizeof(uint16_t) - sizeof(uint16_t) -
(sizeof(uint8_t) * ARY1_LEN) -
sizeof(uint32_t)];
uint32_t crc;
};
これは単純なデータ構造のように見えますが、構造が数十のフィールドを持つように成長すると、絶対的な怪物になります。また、構造体フィールドを追加または削除すると、サイズの計算reserved
も同時に更新する必要があるため、保守性の悪夢でもあります。
構造体の最後に項目が 1 つしかない場合 (チェックサムなど)、値の読み取り/書き込みにヘルパー関数を使用することがあります。これにより、データ構造がクリーンで保守しやすくなりますが、バッファの最後に複数のフィールドがある場合、うまくスケーリングできません。
代わりに次のようなことができれば、非常に役立ちます。
struct overlay {
uint16_t field1;
uint16_t field2;
uint8_t array1[ARY1_LEN];
char reserved[TOTAL_BUFFER_LENGTH -
offsetof(struct overlay, reserved) -
sizeof(uint32_t)];
uint32_t crc;
};
残念ながら、offsetof
は完全なオブジェクト型でしか機能しません。これは の定義の途中であるためstruct overlay
、その型はまだ完全ではありません。
この種のことを行うための、よりクリーンで保守しやすい方法はありますか? 基本的に、最初と最後にフィールドがあり、残りのスペースが予約/未使用の固定長構造が必要です。