【概要】
Arduino環境において、longは符号付き32ビット整数を保持するための基本データ型です。厳密には「関数」ではなく「データ型」ですが、Arduinoの標準ライブラリにおいて非常に重要な役割を果たします。特に、システム動作時間の取得を行うmillis()やmicros()といった関数は、このlong型(正確にはその符号なし版であるunsigned long)を戻り値として返すため、時間の管理や数値演算における基盤として不可欠な要素です。
【仕様】
- データ型:
long(signed 32-bit integer) - サイズ: 32ビット(4バイト)
- 表現範囲: -2,147,483,648 ~ 2,147,483,647
- 初期状態: 未初期化の場合、メモリ内の不定な値(ゴミデータ)を保持します。確実な動作のため、常に明示的な初期化(例:
long value = 0;)が推奨されます。
【技術的特徴】
- プラットフォーム依存性:
- AVRアーキテクチャ(Arduino Uno, Nano, Megaなど):
int型が16ビットであるのに対し、long型は32ビットとして定義されます。この差異を理解せずにintで大きな数値を扱うと、意図しないオーバーフローが発生します。 - ARM/ESP32アーキテクチャ: 一般的に
int型もlong型も32ビットとして扱われます。
- AVRアーキテクチャ(Arduino Uno, Nano, Megaなど):
- プロモーション規則: 演算において、より小さな整数型(
byte,int等)とlong型が混在する場合、C++の型昇格規則に基づき、結果はlong型として評価されます。 - 2の補数表現: 負の数は2の補数形式で符号付きとして表現されます。
【注意点】
- オーバーフローの挙動: 32ビットの最大値を超えた計算を行うと、ラップアラウンド(負の方向への回り込み)が発生します。特に累積値の計算において注意が必要です。
millis()との整合性:millis()関数はunsigned long(符号なし32ビット整数)を返します。これを符号付きのlongに代入すると、システム起動から約24.8日経過した時点で負の値として解釈される可能性があります。時間計測には必ずunsigned longを使用してください。- 符号付きと符号なしの比較:
longとunsigned longを直接比較すると、符号付きの負の数値が非常に大きな正の数値として比較される「符号の罠」が発生します。比較演算を行う際は、適切な型キャストまたは符号の考慮が必要です。
【サンプルコード】
/*
* long型の挙動およびmillis()との連携確認用サンプル
* 32ビット演算における時間管理の標準的な実装
*/
unsigned long previousMillis = 0;
const long interval = 1000; // 1000ms (1秒) のインターバル
void setup() {
Serial.begin(9600);
Serial.println("Timer Started.");
}
void loop() {
unsigned long currentMillis = millis(); // unsigned long型で取得
// 時間差の計算。long型の範囲内で安全に比較可能
if (currentMillis - previousMillis >= (unsigned long)interval) {
previousMillis = currentMillis;
Serial.print("Elapsed: ");
Serial.println(currentMillis);
}
}
【活用例】
- 非同期タイマーの実装:
millis()をベースとした、delay()関数を使わないマルチタスク的な処理制御。 - センサーデータの累積: 高精度なパルス計数(エンコーダのカウントなど)において、16ビットを超える数値を正確に保持・計算する場合。
- 距離・位置の計算: mm単位などの大きな数値を扱う距離計算における、整数演算の基本型としての利用。


コメント