C/C++で配列の長さの求め方です。
超基本中の基本なのですが、しばらくC/C++の配列を使っていないと
アレレってことになってしまいます。
今日はそれでハマりました。
sizeofを使って配列の長さ(要素数)を求めたはずが、
なんでか落ちる…バッファオーバーランっぽい。
こんなコードです。
int hoge[20]; for (int i = 0; i < sizeof(hoge); i++) { hoge[i] = 0; // バッファオーバーランしちゃうよーぎえー(´・ω・`) }
memset()
使えよとかそういう問題ではありません。
ちなみに、次のパターンなら通常の環境の場合バッファオーバーランにはなりません
char hoge[20]; for (int i = 0; i < sizeof(hoge); i++) { hoge[i] = 0; // おっけー!一応ね… }
そうです。char型の場合だと1バイトなので割る必要はないですが、
int型だと1つあたり4byteなので(環境依存ですが……)一つあたりの型の長さの分で
割ってやらなければいけません。
結論
配列の長さを求めるには
sizeof(array) / sizeof(array[0])
としてやる。
検証用のコード(C99)
#include <stdio.h> int main() { const int ArrSize = 50; int arr[ArrSize]; printf("sizeof(int) : %d\n", sizeof(int)); printf("sizeof(arr[0]) : %d\n", sizeof(arr[0])); printf("sizeof(arr) : %d\n", sizeof(arr)); printf("sizeof(arr) / sizeof(int) : %d\n", sizeof(arr) / sizeof(int)); printf("sizeof(arr) / sizeof(arr[0]) : %d\n", sizeof(arr) / sizeof(arr[0])); }
※C99以前ではconst定数を配列のサイズに指定することができないので、
その場合は#define
するしかありません。
実行結果
sizeof(int) : 4 sizeof(arr[0]) : 4 sizeof(arr) : 200 sizeof(arr) / sizeof(int) : 50 sizeof(arr) / sizeof(arr[0]) : 50
検証用のコード(C++)
#include <iostream> int main() { using namespace std; const int ArrSize = 50; int arr[ArrSize]; cout << "sizeof(int) : " << sizeof(int) << endl; cout << "sizeof(arr[0]) : " << sizeof(arr[0]) << endl; cout << "sizeof(arr) : " << sizeof(arr) << endl; cout << "sizeof(arr) / sizeof(int) : " << sizeof(arr) / sizeof(int) << endl; cout << "sizeof(arr) / sizeof(arr[0]) : " << sizeof(arr) / sizeof(arr[0]) << endl; }
実行結果
sizeof(int) : 4 sizeof(arr[0]) : 4 sizeof(arr) : 200 sizeof(arr) / sizeof(int) : 50 sizeof(arr) / sizeof(arr[0]) : 50
マクロを使ったおまけ(C++)
#include <iostream> #define ARRAY_LEN(ARR) (sizeof(ARR) / sizeof((ARR)[0])) int main() { using namespace std; const int ArrSize = 50; int arr[ArrSize]; cout << "ARRAY_LEN : " << ARRAY_LEN(arr) << endl; for (int i = 0; i < ARRAY_LEN(arr); i++) { // do anything ... } }
※上記のマクロは多少落とし穴がありますが、
そこはそんなあほなことするなよでよろしくお願いします。
頑張っているところがありました。
※なお、たまに見かける、やっちまったなーなコードは関数で配列をポインタとして
受け取ったもの*1を
sizeof
して配列の長さを出すつもりが、
実際にはポインタのサイズ(長さ)しか出していないというものです。
そういう場合は長さを渡すか、その配列の長さ用に定義した定数を使うしかないです。
配列のサイズを求める関数とかって標準であるのかなぁ……
*1:この場合 int *arr と受取ろうが、 int arr[] と受取ろうが関数の引数の場合、どっちも単なるポインタとなってしまう