C言語では、配列は値渡しではなく、ポインタで渡されます。配列を引数として渡すと、実際には配列の最初の要素へのポインタが関数に渡されます。これにより、関数は元の配列を修正しますが、そのコピーは修正しません。
例えば:
void fillArray(int arr[], int n) { for (int i = 0; i < n; ++i) arr[i] = i*i; } int main() { int myarr[5]; fillArray(myarr, 5); // OK }
関数内では:
sizeof(arr)を使用して元の配列のサイズを知ることはできません。これはポインタのサイズを返し、配列のサイズではありません。配列と安全に正しく作業する方法:
const int *arrを渡す。質問: 関数内で
int arr[]という引数を使用して、元の渡された配列のサイズをsizeof(arr)で知ることはできますか?
回答: いいえ、できません!sizeof(arr)は関数内でポインタのサイズ(例えば、4バイトまたは8バイト)を返しますが、配列のサイズは返しません。
例:
void f(int arr[]) { printf("%zu\n", sizeof(arr)); // ポインタのサイズ、配列ではない! } int main() { int x[10]; f(x); // 通常8(x86_64)または4(x86)を出力 }
逸話
産業プロジェクトで、配列をコピーする関数は、関数内で
sizeof(arr)/sizeof(int)を使用して配列の長さを動的に計算しようとしました。これにより、常にサイズが1(8/8)になり、配列の一部のみがコピーされ、データが予測不可能な方法で上書きされました。
逸話
あるネットワークアプリケーションで、データ送信関数はバッファを配列として扱い、サイズを明示的に指定しなかったため、全バッファが送信されず、また配列の境界外でゴミデータを読み込むことになり、送信エラーや接続の不安定さが引き起こされました。
逸話
画像処理ライブラリを書いている際に、プログラマーは画像配列を塗りつぶす関数にサイズの必須パラメータを追加しませんでした。これによりバッファオーバーフローが発生し、特定の入力でプログラムがクラッシュしましたが、これは統合テストで大きな画像を使用して初めて発見されました。