HOWTO · Arduino

Arduino 陣列長度

使用 `sizeof` 運算子計算完整固定大小 Arduino 陣列的元素個數,並了解如何將其用於迴圈界限。

本頁內容

在完整的固定大小陣列仍位於作用域內時,可用 sizeof(array) / sizeof(array[0]) 計算 Arduino 陣列的元素個數。結果就是元素數量,可用作迴圈界限。sizeof() 計算的是位元組數;相除後,便能將陣列的總位元組數換算成元素個數。

使用 sizeof() 計算 Arduino 陣列的長度

例如,若 values 包含五個整數,sizeof(values) / sizeof(values[0]) 的結果就是 5。這是因為在程式的這個位置,values 指的是完整陣列。固定大小的其他元素型別陣列也能使用相同的運算式,因為分母會計算該陣列第一個元素的大小。

為什麼 sizeof() 的除法有效

sizeof 是 C++ 運算子,不是函式。用在陣列上時,它會回報整個陣列所占的位元組數;用在 array[0] 上時,則會回報單一元素所占的位元組數。第一個大小除以第二個大小,就會得到元素個數,前提是兩個運算式都指向實際陣列及其元素型別。

例如,即使不必假設特定開發板上的 float 占用多少位元組,這個運算式仍可計算固定大小的 float 陣列元素個數。兩個大小會依相同的型別和目標平台決定,其比值就是元素個數。不要把位元組數硬寫成 4 之類的常數:迴圈需要的是元素個數。

將公式套用到其他陣列型別與維度

元素型別不會改變公式。若陣列名稱是 readings,可使用 sizeof(readings) / sizeof(readings[0])。當初始化清單變動時,這很實用:計算出的數量會隨陣列宣告更新,不必另外維護一個數字。

對於固定大小的二維陣列,將整個陣列的大小除以第一列的大小,可計算列數;將第一列的大小除以其中第一個元素的大小,則可計算欄數。例如,對 int matrix[3][4] 而言,sizeof(matrix) / sizeof(matrix[0]) 得到列數,而 sizeof(matrix[0]) / sizeof(matrix[0][0]) 得到欄數。這些運算式表示宣告時指定的維度,不會得知會在執行期間變動的集合目前有多少元素。

將陣列傳入函式時處理陣列長度

陣列作為函式參數傳入時,該參數會被視為指向第一個元素的指標。在函式內,sizeof(parameter) 計算的是指標的大小,而不是呼叫端完整陣列的大小。因此,將它除以 sizeof(parameter[0]) 無法還原原始陣列的元素個數。

請將元素個數作為另一個參數傳入,並用它作為迴圈界限。在完整陣列仍位於作用域內的呼叫位置計算個數:printValues(values, sizeof(values) / sizeof(values[0]))。如此一來,函式就能剛好處理指定數量的元素。若要透過多個函式傳遞陣列,請一併傳遞元素個數,讓每個函式都能取得所需資訊。

sizeof 公式適用於運算式中可取得完整型別的固定大小陣列。它不會追蹤執行期間大小會改變或動態配置的集合。對於這類集合,請使用集合本身的長度機制保存或取得元素個數。

在完整的 Arduino 草圖中使用陣列長度

在 Arduino 草圖中,可在檔案層級或 setup() 內宣告固定大小陣列,並在同一個作用域計算元素個數。接著從索引 0 開始迴圈,直到索引小於該數量為止,確保每次存取都在陣列範圍內。下方草圖在開發板上使用 Arduino 的 Serial。若以一般 C++ 編譯,簡單的本機 Serial 替代物便可讓相同的 setup() 邏輯輸出至標準輸出。

本節中的程式碼以及顯示的標籤或輸出仍為英文。

#include <stddef.h>

#ifdef ARDUINO
#include <Arduino.h>
#else
#include <iostream>

class SerialPort {
public:
  void begin(unsigned long) {}
  void print(const char* value) { std::cout << value; }
  template <typename T>
  void println(const T& value) { std::cout << value << '\n'; }
};
SerialPort Serial;
#endif

int values[] = {10, 20, 30, 40, 50};
const size_t valueCount = sizeof(values) / sizeof(values[0]);

void setup() {
  Serial.begin(9600);
  for (size_t i = 0; i < valueCount; ++i) {
    Serial.println(values[i]);
  }
  Serial.print("Count: ");
  Serial.println(valueCount);
}

void loop() {
}

#ifndef ARDUINO
int main() {
  setup();
}
#endif
10
20
30
40
50
Count: 5

在開發板上,請上傳草圖,並以 9600 鮑率開啟 Serial Monitor 查看數值和元素個數。若將迴圈移至輔助函式,請連同陣列明確傳入 valueCount;輔助函式無法從指標參數還原原始陣列長度。