Cプログラミング
 Computer >> コンピューター >  >> プログラミング >> Cプログラミング

C言語における配列の範囲外インデックスとは?

配列の範囲外インデックスとは

配列の範囲外インデックス(インデックスアウトオブバウンズ)とは、配列で定義された有効な範囲を超えて要素にアクセスすることを指します。

例えば、4つの要素を持つ配列の場合、インデックスは0から3までの範囲になります。つまり、インデックス0から3までの要素にアクセスできるということです。

しかし、3より大きいインデックスを使用すると、それは「範囲外インデックス」と呼ばれます。

範囲外の配列インデックスを使用した場合でも、コンパイラはエラーを出さずにコンパイルし、プログラムは実行されます。しかし、正しい結果は一切保証されません。

実行結果は不確実なものとなり、予期しない値の読み書き、メモリ破壊、プログラムの異常終了など、さまざまな問題を引き起こす可能性があります。これはC言語では「未定義動作(undefined behavior)」に分類されます。そのため、配列のインデックスを扱う際には十分な注意が推奨されます。

サンプルプログラム

以下は、配列における範囲外インデックスを示すC言語のプログラムです。

#include<stdio.h>
int main(void){
   int std[4];
   int i;
   std[0] = 100; //有効
   std[1] = 200; //有効
   std[2] = 300; //有効
   std[3] = 400; //有効
   std[4] = 500; //無効(範囲外インデックス)
   //すべての要素を表示
   for( i=0; i<5; i++ )
      printf("std[%d]: %d\n",i,std[i]);
   return 0;
}

実行結果

上記のプログラムを実行すると、以下のような結果が出力されます。

std[0]: 100
std[1]: 200
std[2]: 300
std[3]: 400
std[4]: 2314

解説

このプログラムでは、配列のサイズは4であるため、有効なインデックスはstd[0]からstd[3]までです。しかし、ここでは範囲外であるstd[4]に値500を代入しています。

そのため、プログラム自体は正常にコンパイルされ、実行も完了します。しかし、値を表示してみると、std[4]の値は代入した500ではなく、2314というでたらめな値(ガベージ値)が出力されています。

これは、std[4]が配列の範囲外のメモリ領域を指しており、そこに書き込まれた500が別の用途で上書きされたり、メモリ上の別のデータが読み出されたりするためです。このように、範囲外アクセスはコンパイル時には検出されず、実行時に予測不能な挙動を引き起こすため、非常に危険です。

範囲外アクセスを防ぐポイント

  • 配列のサイズを意識し、ループの条件式は「i < 配列サイズ」とする
  • 配列サイズをマクロや定数で定義し、ハードコーディングを避ける
  • 可能であれば、静的解析ツールやサニタイザ(AddressSanitizerなど)を活用して検出する
  1. C#のArrayクラスとは?主なプロパティと使い方をわかりやすく解説

    C#のArrayクラスとは Arrayクラスは、C#におけるすべての配列の基底クラス(基本クラス)です。このクラスはSystem名前空間で定義されており、配列を操作するためのさまざまなプロパティやメソッドが用意されています。 通常、C#で配列を作成すると、その配列は暗黙的にこのArrayクラスから派生しているため、Lengthなどの便利な機能をすぐに利用できます。 Arrayクラスの主なプロパティ一覧 以下の表は、Arrayクラスで特によく使用される代表的なプロパティをまとめたものです。 番号 プロパティと説明 1 IsFixedSize 配列が固定サイズであるかどうかを示す値を取得

  2. JavaのArrayIndexOutOfBoundsExceptionとは?発生原因と対処法を解説

    配列とインデックスの基本 配列(Array)とは、同じ型の要素を固定サイズで順番に格納するためのデータ構造(コンテナ/オブジェクト)です。配列のサイズ(長さ)は生成時に決定され、後から変更することはできません。 配列内の各要素の位置は「インデックス(添字)」と呼ばれます。Javaの配列は0始まりのため、最初の要素はインデックス0、2番目の要素はインデックス1、というように順に番号が割り当てられます。 配列の各要素へは、「配列名[インデックス]」という形式の式を使ってアクセスします。 System.out.println(myArray[3]); // 1457 が出力される たとえばサイズ7