組み込みC言語の構造体:定義・活用・メモリ最適化の実践ガイド
構造体は効率的な組み込みCプログラミングの基石です。本記事では実践的な応用、宣言構文、データアライメントがメモリ使用量に与える影響を探ります。構造体メンバを戦略的に並べ替えることで、データオブジェクトのフットプリントを削減できることが多々あり、これはリソース制約環境で極めて重要な考慮事項です。
本記事では組み込みCにおける構造体の簡潔かつ包括的な概要を提供します。実世界での応用、正しい宣言方法、構造体サイズに影響するデータアライメントの微妙なルールをカバーします。
構造体
同じ型の複数の変数が論理的な関係を持つ場合、配列は便利なグループ化手段です。例えば、音声入力をデジタル化するADCから直近50サンプルを保持するには:
uint16_t voice[50];
ここではuint16_tはstdint.hで定義される符号なし16ビット整数で、プラットフォーム間で一貫したサイズを保証します。
しかし、異なる型の変数をグループ化する必要がある場合、例えばサンプル配列とADCのサンプリングレートを別々の独立変数として宣言すると不必要なオーバーヘッドが生じます。代わりに、それらを構造体にカプセル化できます:
struct record { uint16_t voice[50]; float sample_rate; };
record構造体はuint16_tの配列とfloatを単一の論理的に接続されたデータオブジェクトにまとめます。
なぜ構造体が重要なのか?
構造体は異種変数を凝集性のある単位として関連付け、操作をシンプルにし可読性を高めます。リンクリストやメッセージバッファなど、組み込み通信とセンサデータ処理で普及しているより複雑なデータ構造の基盤となります。
例えば、マイクロコントローラのメモリマップドペリフェラルは、ハードウェアレジスタレイアウトを反映した構造体として表現されることが多く、メンバ構文でレジスタへの直感的なアクセスを可能にします。

図1. 構造体を用いたリンクリスト実装例。

図2. STM32 MCUのメモリマップ。Embedded Systems with ARM提供の画像。
構造体の宣言
まず構造体テンプレートを定義します。例:
struct record { uint16_t voice[4]; float sample_rate; };
テンプレート自体はメモリを消費しません。その型の変数を宣言した時点で割り当てられます:
struct record mic1;
これでmic1は4つのuint16_t要素と1つのfloat分のスペースを占有します。ドット演算子でメンバにアクセス:
mic1.voice[0] = 100; float fs = mic1.sample_rate;
構造体宣言のその他の方法
最も一般的なパターンは構造体を先に定義し、その後変数を宣言するものですが、C言語には代替構文があります:
構文1:タグと変数を同時に
struct record { uint16_t voice[4]; float sample_rate; } mic1;
以降の変数は別個に宣言可能:
struct record mic2;
構文2:無名テンプレート
struct { uint16_t voice[4]; float sample_rate; } mic1;
ここではテンプレートに名前がないため、他で再利用できません。
構文3:無名ネスト構造体
struct test { struct { float f; char a; }; } test_var;
内部メンバに直接アクセス:
test_var.f = 1.2f;
無名構造体は冗長性を減らせますが、明確さのため慎重に使用すべきです。
構造体のメモリレイアウト
C標準は、メンバが宣言順にメモリ上で順次配置されることを保証します。例:
struct Test2 { uint8_t c; uint32_t d; uint8_t e; uint16_t f; } MyStruct;
32ビットマシンでは、uint32_tが4バイト境界にアラインされるためのパディングによりsizeof(MyStruct)は12バイトになります。メンバを並べ替えるとパディングを排除できます:
struct Test2 { uint32_t d; uint16_t f; uint8_t c; uint8_t e; } MyStruct;
これでsizeof(MyStruct)は8バイトに縮小します。メモリ制約のあるファームウェアでは貴重な節約です。

図3. データアライメントにより構造体のメモリレイアウトにパディングが追加される例。
まとめ
- 構造体を使えば異種変数を単一の管理しやすい単位にバンドルでき、コードの明確さと効率が向上する。
- カスタムデータ構造はデバイス間メッセージングやセンサデータ格納などのタスクを支える。
- メモリマップドペリフェラルのハードウェアレジスタマッピングに不可欠。
- アライメントを尊重してメンバを並べ替えると構造体サイズを大幅に削減できる。
組み込みCチュートリアルをさらに探すにはこちら。
埋め込み
- 産業用IoT(IIoT):定義、範囲、産業への影響
- メンテナンスデータの理解:信頼性の高い資産管理の鍵
- 現代木工マスター:トレンド・テクノロジー・技術のすべて
- バイフォールドヒンジとは? 特徴、メリット、用途
- デッキスクリュー完全ガイド:種類・メリット・木ネジとの違い
- スプリングエナジャイズドシール:設計、機能、産業メリット
- 木ネジ解説:種類・特徴・選定のポイント
- 鋼合金を徹底解説:種類、組成、用途
- 「信頼性のインターネット」におけるデータ活用:効果的管理のための戦略
- 難燃性金属とは? 特性と用途の専門的概観
- Javaデータ構造: 従来クラス(Vector/Stack/Hashtable等)とコレクションフレームワーク概要