array の解説と実装リファレンス

記事内には広告が含まれています。

array の解説と実装リファレンス

【概要】

Arduino(C/C++)における「array(配列)」は、同一のデータ型を持つ複数の要素をメモリ上の連続した領域に配置するデータ構造です。特定のインデックス(添字)を用いて、各要素への高速なアクセスを実現します。組み込みシステムにおいては、センサーデータのバッファリング、通信プロトコルのパケット処理、信号処理のためのルックアップテーブルなど、効率的なデータ管理の基礎として不可欠な要素です。

【仕様】

基本定義

  • データ型: int, float, char, byte, uint8_t 等、任意の基本型または構造体。
  • インデックス: 0から始まる整数値。
  • サイズ計算: 配列全体に対する要素数の取得は、sizeof(array) / sizeof(array[0]) を用いて算出する。

初期化と宣言

int sensorReadings[5] = {10, 20, 30, 40, 50}; // 静的な初期化
byte buffer[10]; // 未初期化(内容は不定)

【技術的特徴】

メモリ配置とアクセス速度

  • 計算量: 配列要素へのアクセスは O(1)であり、インデックス計算のみでメモリのアドレスを特定するため、非常に高速である。
  • ポインタとの関係: 配列名は、メモリ上の最初の要素を指すポインタとして評価される。そのため、ポインタ演算を用いることで要素間の移動を効率的に記述できる。
  • 連続性: 要素はメモリ上で連続して配置されるため、空間局所性が高く、キャッシュ効率(より高度なマイコンにおいて)やシリアルなデータ転送に適している。

スタックとメモリセグメント

  • Arduino(特にAVRマイコン)において、静的に定義された配列はデータセグメントまたはスタックに配置される。
  • const 修飾子を付与した配列は、設計によっては PROGMEM を用いてRAMを消費せずにFlashメモリ上に配置することが可能であり、リソース制約のある環境では重要な最適化手法となる。

【注意点】

境界外アクセス(Buffer Overflow)

  • C/C++標準の配列には、範囲チェック(Bounds Checking)の機能がない。指定したインデックスが配列のサイズを超えている場合、意図しないメモリ領域を破壊、または読み取るため、システムが不安定化する原因となる。

リソース制約(SRAM)

  • Arduino Uno等の低メモリ環境では、巨大な配列の宣言はスタックオーバーフローを引き起こす。配列のサイズは、使用可能なSRAM容量を考慮し、最小限に設計する必要がある。

可変長配列(VLA)

  • int arr[n]; のように実行時にサイズを決定する可変長配列は、コンパイラや標準規格によってはサポートされない、あるいはスタックを過度に消費する可能性がある。動的なサイズ変更が必要な場合は、std::vector(メモリ管理に注意)や動的メモリ確保(malloc / new)を検討するが、組み込みではメモリ断片化を防ぐため、あらかじめ最大サイズを確保する静的配列の使用が推奨される。

【サンプルコード】

#include <Arduino.h>

// センサーデータの移動平均用バッファ(静的配列)
const int BUFFER_SIZE = 8;
byte dataBuffer[BUFFER_SIZE] = {0};
int bufferIndex = 0;

void setup() {
  Serial.begin(9600);
}

void loop() {
  // 擬似的なデータ取得
  byte newData = analogRead(A0) % 256; 

  // 配列への格納(リングバッファ的な動作)
  dataBuffer[bufferIndex] = newData;
  bufferIndex = (bufferIndex + 1) % BUFFER_SIZE;

  // 配列の平均値を計算
  long sum = 0;
  for (int i = 0; i < BUFFER_SIZE; i++) {
    sum += dataBuffer[i];
  }

  Serial.print("Average: ");
  Serial.println(sum / BUFFER_SIZE);
  delay(100);
}

【活用例】

  1. 移動平均フィルタ(Moving Average Filter):
    センサーのノイズ除去のため、直近 N 個のサンプルを配列に保持し、平均値を算出する。
  2. 通信プロトコルバッファ:
    UARTやSPI通信において、受信したバイナリデータを一旦配列に蓄積し、ヘッダーとペイロードを解析する。
  3. ルックアップテーブル(LUT):
    複雑な三角関数や対数計算をリアルタイムで実行する代わりに、あらかじめ計算済みの値を配列に格納しておき、インデックス参照で取得することでCPU負荷を軽減する。

コメント

タイトルとURLをコピーしました