配列を扱う時に犯しやすく、重大なバグにつながる可能性のある間違いのメモ。
配列のおさらい
配列は変数の集合であり、一つの変数で複数の値(要素)を扱うことができる。
宣言
int a [5] = {5,6,7,8,9};
int b [] = {1,2,3,4};
int c [4];
~~~~~~~~~
[]内で要素の数を指定し、{}内に要素を記述する。
要素の数を指定しない(b)で、または要素を指定しない(c)で初期化することもできる。
### 要素
それぞれの要素は変数名と添字によって表される。上記の例であれば以下のようになる。
aは以下の要素の集まりである。
a[0]=5,a[1]=6,a[2]=7,a[3]=8,a[4]=9
# 配列指定時のバッファオーバーフロー
配列で指定した要素を超えて要素を書き込んでしまうこと。
int a[5];と指定したにも関わらずa[10]=10;と書き込むなど。
## なぜ見つけにくいか?
エラーがでない場合があるため。プログラムに割り当てられたメモリ内に空きがある場合、指定していない領域に意図しない形で書き込みが行われるが、書き込み自体は行われるためエラーは出ない。しかし他処理で使うメモリ領域に書き込みが行われると重大な問題となる可能性がある。
## 注意が必要な点
### 添字のカウント
添字は0からであり1からではない。
下記はaの5つの要素に1を入れる、という処理をしようとしているが、
a[0]が空、a[1]〜a[4]は1、そして宣言していないa[5]に1を書き込んでおり、どこか不明なメモリ領域にa[5]の値1を記録してしまう。
int a[5];
for ( i=1;i<=5;i++){
a[i]=1;
}
### 文字列を扱う場合
char型の配列を扱う場合、文字数+1の大きさ(要素数)が必要なことに注意。char型の場合最後にNull終点文字が自動的に付加されるため。
下記ではoneは3文字だが実際に必要なのはNull終点含め4文字分であり、オーバーフローが起こる。
~~~~~~~~~~~~
char a[3];
char b[]="one";
strcpy(a,b);
~~~~~~~~~~~~~
あと致命的な間違いにはならないが、Arduinoのスケッチ(というかC++)では「配列変数から配列変数への直接代入はできない」というのを忘れがちなので心に留めておく。