for の解説と実装リファレンス
【概要】
for 文は、C/C++言語(Arduinoの基盤言語)における制御構造の一つであり、指定された回数または条件を満たすまで、特定のコードブロックを繰り返し実行するために使用される。組み込みシステムにおいては、配列の走査、特定のビット操作の反復、あるいは一定周期の処理を簡潔に記述するために不可欠な構文である。
【仕様】
for 文は以下の基本構文に従い、3つのセクションで構成される。
for (初期化式; 条件式; 更新式) {
// 実行されるコードブロック
}
- 初期化式 (Initialization): ループの開始前に一度だけ実行される。主にループカウンタの宣言と初期化を行う。
- 条件式 (Condition): 各反復の開始前に評価される。結果が「真(non-zero)」である限り、ループ内のブロックが実行される。
- 更新式 (Update): ループ内のコードブロックが実行された直後に実行される。カウンタの増減や、ポインタの移動などを行う。
- データ型: 初期化式で定義される変数の型は、用途に応じて
int,long,uint16_t,uint32_tなどが選択される。
【技術的特徴】
-
コンパイルレベルの挙動:
for文は高レベルな抽象化構造であるが、コンパイル時にはCPUの分岐命令(JUMP)および比較命令(CMP)に変換される。そのため、while文と比較して実行効率に有意な差が生じることは稀であるが、コードの可読性と構造の明確性において優位性がある。 -
スコープ(Scope):
初期化式内で宣言された変数は、for文のブロック内のみに限定される。これは、ループ外のメモリ領域を汚染せず、メモリ管理を局所化する上で重要な特性である。 -
複雑度:
ループ内の処理が $O(1)$ の場合、for文の全体的な計算量は $O(n)$ となる。組み込み環境では $n$ の最大値を意識し、処理時間がリアルタイム性を損なわないか評価する必要がある。
【注意点】
- ブロッキング動作:
Arduinoのloop()関数内で長いfor文を実行すると、その処理が終わるまで他の処理(loop()内の他の処理)が中断される。時間管理が必要な場合はmillis()を用いた非ブロッキング処理への移行を検討すべきである。 - 整数オーバーフロー:
カウンタ変数にintを使用する場合、特に8ビットマイコン(Arduino Uno等)では最大値(32,767)を超えると負の値に反転し、無限ループの原因となる可能性がある。大きな回数の反復にはunsigned long等の適切な型を選択すること。 - 割り込み(Interrupts)との関係:
for文自体は割り込みを停止させない。しかし、ループ内で共有メモリ(グローバル変数)を操作する場合、割り込みハンドラとの間で競合が発生する可能性がある。必要に応じてnoInterrupts()を使用してクリティカルセクションを保護すること。 - スタック消費:
極端に深いネストや、ループ内で巨大なローカル配列を宣言すると、スタックオーバーフローを引き起こす可能性がある。
【サンプルコード】
1. 基本的なLED点滅(配列走査)
const int ledPins[] = {2, 3, 4}; // LEDのピン番号
void setup() {
for (int i = 0; i < 3; i++) {
pinMode(ledPins[i], OUTPUT);
}
}
void loop() {
for (int i = 0; i < 3; i++) {
digitalWrite(ledPins[i], HIGH);
delay(200);
digitalWrite(ledPins[i], LOW);
}
}
2. ビット演算を伴う反復
// 特定のビット範囲を反復処理する例
void processBits(uint8_t data) {
for (int i = 0; i < 8; i++) {
if (data & (1 << i)) {
// i番目のビットが立っている場合の処理
}
}
}
【活用例】
- センサーデータの平均化: 複数のセンサー値を配列に格納し、
for文で合計を算出して平均を求める。 - 通信プロトコルの実装: UARTやI2C通信において、特定のデータ長に合わせてバイトごとにデータを読み書きする処理。
- PWM信号の生成: 特定の周波数やデューティ比を実現するために、周期的な計算を反復処理する。
- メモリ上のバッファ処理: 受信バッファ内のデータを解析し、特定のシーケンスを抽出する処理。


コメント