標準関数を使う
| 設計内容分類 | 組み込みソフトウェアにおけるC言語記述 |
|---|
実現したい仕様・課題
配列の初期化やコピーをforループで1要素ずつ記述すると、コードが冗長になるうえ、ループ条件の書き間違いによる範囲ミスも起こりがちです。定型的なメモリ操作を、短く、速く、間違いにくく記述したいというのが課題です。
設計のポイント
標準関数を使うことで、値の代入・コピーのためのコードを短く記述できます。配列のゼロクリアは、forループの代わりに memset(a, 0x00, 32); の1行で書け、配列間のコピーも memcpy(a, b, 32); で完結します。記述が短くなるだけでなく、標準ライブラリのmemset/memcpyは処理系ごとに最適化されている(ワード単位の転送やCPUの専用命令を使う実装が多い)ため、素朴な1バイトずつのループより高速に動作することが一般的です。サイズ指定には数値の直書きではなくsizeofを併用し、memset(a, 0x00, sizeof(a)); とすることで、配列サイズ変更への追従と単位(バイト数)の間違い防止を両立します。使用上の注意として、memcpyはコピー元とコピー先の領域が重なっている場合の動作が未定義のため、同一バッファ内での移動など重なりの可能性がある場合はmemmoveを使います。文字列のコピーには、終端まで際限なく書き込むstrcpyではなく、サイズ上限を管理できる関数(snprintf等)の使用を推奨します。また、memsetの値引数はバイト単位で埋められるため、int配列を「全要素1」にする用途には使えない(0と-1/0xFF以外は意図どおりにならない)ことも理解して使い分けます。定型操作を標準関数に寄せることで、コードの意図が読み取りやすくなり、レビューも「サイズ指定が正しいか」の確認に集中できます。
【コード例】
// ループによる初期化・コピー
for (i = 0; i < 32; i++) { a[i] = 0x00; }
for (i = 0; i < 32; i++) { a[i] = b[i]; }
// ↓ 標準関数で簡潔・高速に
memset(a, 0x00, sizeof(a));
memcpy(a, b, sizeof(a));
// 領域が重なる可能性がある場合はmemmove
memmove(&buf[0], &buf[4], len - 4);
補足情報
設計のポイント 一覧
組み込みソフトウェアにおけるC言語記述のポイント
- リングバッファで受信データを取りこぼさない
- switch-caseによるステートマシンの実装
- 割り込みハンドラは短く書く
- constを活用する(ROM配置と書き換え防止)
- ビット演算によるレジスタ・フラグ操作
- 固定幅整数型(stdint.h)を使う
- volatile修飾子を正しく使う
- 構造体の宣言にpackedを指定する
- ソースコードのエンディアン変換
- sizeofを使用する
- 特殊文字の記述にエスケープ文字を使用する
- 変数の初期化漏れを防ぐ
- 外部バスの使用
- sprintf関数を使う
- 列挙型(enum)を使う
- 構造体を使う
- 標準関数を使う
- 条件演算子を使う
- インクリメント演算子を使う
- C言語記述の際はアプリ層とドライバ層に分ける



