6.7.9初期
4静的またはスレッドを持つオブジェクトの初期化子内のすべての式:
ここ
const int a = 5;
a
は、ないC standardによって必要とされる定数式であります記憶期間は定数 式または文字列リテラルでなければならない。
エラーは、C89/C90コンパイラを使用していることを示しています。ユーザーから入力されたa
の入力を読み取って、variable length arrayと宣言することができます。これはC99機能で、自動保存期間があります。
#define
を使用することも別の方法です。しかし、それは単なるテキスト置換であり、自動記憶期間を持つ配列を定義します。 int arr[5];
を自分で定義することと同じです。
ダイナミックストレージ(通常は「ヒープ」とも呼ばれます)にメモリを割り当てる場合は、malloc()
ファミリーファンクションを使用する必要があります。このファンクションは、free()
を呼び出すまでプログラムの実行中に有効です。
(この動作はconst
です.C++はこれとは異なり、期待通りに動作します)。
私はC89でコードをコンパイルする場合、それはで失敗します(GCCもC89/C90でan extensionとしてそれをサポートしていますが)C89はのVLAをサポートしていないため
#include <stdio.h>
int main(){
const int a = 5;
int i;
int arr [a];
for (i = 0; i < 5; i++) {
arr[i] = i * 2;
}
printf("%d", arr[1]);
return 0;
}
$ gcc -Wall -Wextra -std=c89 -pedantic-errors test.c
test.c: In function âmainâ:
test.c:7:4: error: ISO C90 forbids variable length array âarrâ [-Wvla]
int arr [a];
^
。したがって、C99をサポートしていないコンパイラを使用している場合は、VLAを使用することはできません。 たとえば、Visual StudioはC99およびC11のすべての機能を完全にサポートしていません。 Visual studio 2015 support most C99 featuresでも、VLAはその1つではありません。
しかし、同じコードが問題なくC99及びC11にコンパイル:
$ gcc -Wall -Wextra -std=c99 -pedantic-errors t.c
$ gcc -Wall -Wextra -std=c11 -pedantic-errors t.c
可変長配列(のVLA)はC99で追加されたためにです。 VLAはC11標準でオプションになっていることに注意してください。したがって、実装はC11でVLAをサポートしない可能性があります。 実装でVLAがサポートされていないかどうかを確認するには、__STDC_NO_VLA__
に対してテストする必要があります。
__STDC_NO_VLA__
6.10.8.3 Conditional feature macrosから意図1整数定数は、実装が可変長アレイまたは可変 改変タイプをサポートしていないことを示します。
配列サイズがかなり大きい場合、割り当ての失敗を移植可能に見つけることができないため、私は個人的にVLAを使用しません。例えば。
size_t size = 8*1024;
int arr[size];
上記のフラグメントでは、arr
の割り当てに失敗した場合、実行時まで認識できません。メモリの割り当てがプラットフォームに依存する「十分に小さい」サイズとは何ですか?したがって、1台のマシンでは、1MBの割り当てが成功する可能性があり、別のマシンでは失敗する可能性があり、さらに悪いことに、この失敗をキャッチする方法はありません。
したがって、VLAの使用は限られており、特定のプラットフォームで常に成功することがわかっている小型アレイでのみ使用できます。しかし、単に配列のサイズをハードコードして境界条件を処理するだけです。
利用可能な代替案が主に '#define'または' malloc'であるとのあなたの仮定は正しい - それを修正するためにこれらの2つのオプションの1つを選んでください。 l3xの答えは、なぜその理由を説明する良い仕事です。 – GrandOpener