可変長配列

可変長配列 (Variable-Length Array: VLA) について



プログラミングにおける可変長配列(VLA)とは、コンパイル時ではなく、プログラムの実行時にその長さ(サイズ)が決定される配列データ構造のことです。これは、プログラムの実行状況に応じて配列のサイズを動的に変更できるため、柔軟なプログラミングを可能にします。VLAは、特にC99規格で導入され、多くのプログラミング言語で採用されています。

VLAをサポートする主なプログラミング言語



Ada
ALGOL 68 (行の長さは固定)
APL
C99 (C11ではオプション扱い)
C# (unsafeモードのスタック割り当て配列として)
COBOL
Fortran 90
J言語
Object Pascal (Borland Delphiで利用)

メモリ割り当てについて



C言語の規格では、スタック領域とヒープ領域の使い分けを規定していませんが、一般的に、静的変数はスタック領域、動的に確保されたメモリはヒープ領域に割り当てられます。VLAは動的にサイズが決定されますが、多くの処理系(例えばGNU Cコンパイラなど)ではスタック領域に確保されます。

C言語規格では、`sizeof`演算子を使用してVLAのバイト容量を取得できると定められているため、VLAの最大サイズは`SIZE_MAX`バイトに制限されます。しかし、これはあくまで文法上の制限であり、実際には`SIZE_MAX`バイトまでのVLAを確保できる保証はありません。特に、VLAをスタック領域に確保する処理系では、大きなVLAを確保しようとするとスタックオーバーフローが発生するリスクがあります。

`malloc()`などの動的メモリ確保関数は、失敗時に戻り値を返すことでエラーを通知できますが、静的配列やVLAの確保失敗は、セグメンテーション違反などのシグナルによってしか検知できません。そのため、`malloc()`と`free()`を繰り返す処理を全てVLAに置き換えることは難しい場合があります。

変数へのアクセス



一部のプログラミング言語では、ポインタを介してVLAにアクセスできますが、その際、VLAは不完全な型と見なされるため、デリファレンス(間接参照)するとサイズを取得できなくなることがあります。

VLAの利用例



C99での例


c
void read_and_process(int size, float data[size]);

void process_data(int size) {
float array[size];
// 配列を初期化する処理
read_and_process(size, array);
}


この例では、関数`process_data`内で、引数`size`で指定されたサイズのVLA `array`が宣言され、`read_and_process`関数に渡されます。VLAは自動変数であるため、`process_data`関数を抜けるとメモリは自動的に解放されます。

注意点: C99では、関数呼び出しにおいて、可変長配列のサイズパラメータは、配列パラメータよりも前に記述する必要があります。

Adaでの例


ada
procedure Process_Data(Size : Integer) is
Data : array (1 .. Size) of Float;
begin
-- Dataを処理するコード
Process(Data);
end Process_Data;

procedure Process(Data : array of Float) is
begin
-- Dataを使用する処理
end Process;


Adaでは、配列は境界を保持しているため、`Process`関数に長さを明示的に渡す必要はありません。

Fortran 90での例


fortran
subroutine process_data(size, array)
implicit none
integer, intent(in) :: size
real, dimension(size), intent(inout) :: array

! 配列を処理するコード
end subroutine process_data

subroutine my_function()
implicit none
integer :: size
real, allocatable, dimension(:) :: array

size = 10
allocate(array(size))
call process_data(size, array)
deallocate(array)
end subroutine my_function


Fortran 90では、プロシージャインターフェースをコンパイル時に検査できます。Fortran 90以前のインターフェースを使用する場合は、配列の長さを引数として明示的に渡す必要があります。

COBOLでの例


cobol
01 DEPT-PERSON-TABLE.
05 DEPT-PERSON OCCURS DEPENDING ON PEOPLE-CNT.
10 PERSON-NAME PIC X(30).
10 PERSON-AGE PIC 99.


この例では、`PEOPLE-CNT`の値によってサイズが決定される可変長配列`DEPT-PERSON`を宣言しています。

C#での例


csharp
unsafe void processData(int size)
{
int
array = stackalloc int[size];
// 配列を処理するコード
}


C#では、`unsafe`キーワードを使用して、スタックに可変長配列を割り当てることができます。

動的割り当てと自動割り当て



Java.NET Frameworkなどの言語は、配列オブジェクトをヒープに割り当てるため、VLAとはみなされません。これらの言語では、配列に自動記憶期間という概念はありません。(ただし、コンパイラは、可能な限りヒープ割り当てをスタック上に最適化することがあります。)

まとめ



可変長配列(VLA)は、プログラムの柔軟性を高める強力なツールですが、メモリ管理やスタックオーバーフローのリスクに注意して使用する必要があります。特に、スタック領域にVLAを確保する場合は、サイズの上限を考慮し、適切なエラー処理を行うことが重要です。

もう一度検索

【記事の利用について】

タイトルと記事文章は、記事のあるページにリンクを張っていただければ、無料で利用できます。
※画像は、利用できませんのでご注意ください。

【リンクついて】

リンクフリーです。