+= (compound addition) の解説と実装リファレンス
【概要】
+= は、CおよびC++言語(Arduinoの基礎言語)において提供される複合代入演算子(Compound Assignment Operator)です。この演算子は、左辺の変数に対して右辺の値を加算し、その結果を再び左辺の変数に代入する操作を1つの式で行います。
数学的な表現では x += y は x = x + y と等価です。これは、変数の値を更新しながら、元の変数への参照を維持する際に使用される標準的な構文です。
【仕様】
| 項目 | 仕様内容 |
| 構文 | variable += expression; |
| 左辺 (LHS) | 変更可能な変数(L-value)。定数やリテラルは使用不可。 |
| 右辺 (RHS) | 数値、変数、または計算式(R-value)。 |
| データ型 | int, float, double, long, unsigned int など、算術演算が定義されているすべての型。 |
| 動作原理 | 1. 左辺の現在の値をメモリから読み出す。
2. 右辺の値を加算する。
3. 加算結果を左辺のメモリ位置に書き戻す。 |
【技術的特徴】
1. コンパイラの最適化
現代のコンパイラ(GCC等)は、x = x + y と x += y をほぼ同等のマシンコードに変換しますが、+= を使用することでコードの可読性が向上し、意図(「現在の値を更新する」こと)が明確になります。
2. 演算子のオーバーロード
Arduino(C++)環境では、自作クラスのメンバ変数に対して演算子オーバーロードを定義することで、オブジェクトに対する += 操作をカスタマイズすることが可能です。
3. 類似演算子との比較
+(Addition): 新しい値を生成するが、元の変数は変更しない。+=(Compound Addition): 元の変数の状態を直接更新する。
【注意点】
1. 非原子性(Non-Atomicity)と競合状態
重要: += はアトミックな操作ではありません。CPUレベルでは「読み出し→加算→書き込み」の3ステップで実行されます。マルチタスク処理や割り込み(ISR)を使用している環境において、共有変数に対して += を使用すると、競合状態(Race Condition)が発生する可能性があります。
– 対策: 共有変数には volatile キーワードを使用し、必要に応じてクリティカルセクション(割り込み禁止等)で保護するか、アトミック操作を使用してください。
2. オーバーフロー(Overflow)
変数の型(例: uint8_t)の最大値を越える加算を行った場合、値はラップアラウンド(回り込み)します。例えば、uint8_t の最大値 255 に対し +1 を行うと 0 に戻ります。
3. 浮動小数点数の精度
float や double 型に対する累積的な += 操作は、浮動小数点数の丸め誤差により、計算回数が増えるほど誤差が蓄積する可能性があります。
【サンプルコード】
// センサーデータの累積加算例
int total_distance = 0;
const int sensor_read = 10;
void setup() {
Serial.begin(9600);
}
void loop() {
// 複合代入演算子による累積
total_distance += sensor_read;
Serial.print("Current Total: ");
Serial.println(total_distance);
delay(1000);
}
【活用例】
- カウンタの実装:
ボタンの押し込み回数や、パルス信号のカウント数を記録する際に使用します。
pulse_count += 1; - 移動平均フィルタの基礎:
センサーデータの合算値を保持するバッファの更新に使用します。
sum += new_sample; - PID制御アルゴリズム:
誤差の累積(I項)を計算する際に、現在の誤差を累積値に加算する処理で使用します。
integral += error * dt; - ゲーム開発(Arduino系):
キャラクターの座標更新やスコアの加算など、状態の更新を簡潔に記述する際に多用されます。


コメント