グローバル配列のサイズを整数定数にする必要があるのはなぜですか?


8

C ++では、あるサイズのグローバル配列を宣言してみました。エラーが発生しました:

バインドされた配列は ']'トークンの前の整数定数ではありません

しかし、main()関数内で同じ型の配列を宣言すると、うまく機能します。

ここに異なる動作があるのはなぜですか?

int y=5;
int arr[y];         //When I comment this line it works fine

int main()
{
    int x=5;
    int arr2[x];        // This line doesn't show any error.
}

編集:多くの人が、この質問は「配列の境界が ']'トークンの前の整数定数ではありません」というエラーの複製であると示唆しています。しかし、その質問は、なぜ異なる行動があるのか​​には答えません。


3
でもmain、これは合法ではなく、VLA拡張を使用します。
Jarod42

4
C ++では、すべての配列の境界には、コンパイル時に認識される値が必要です。そのようなコードが配置されたときにmainコンパイラが「受け入れる」場合:C ++標準でサポートされていない場合でも、VLAをコンパイルできるようにするコンパイラ拡張機能を使用しています。
AlgirdasPreidžius

2
「コンパイラエラーなし」と「正常に機能している」を混同しないでください。この場合、あなたのコードは、非標準のコンパイラ提供の拡張に依存していることを意味し、「細かい作業」、すなわち、それは大丈夫っぽいですが、それは、ポータブルC ++イマイチ
idclev 463035818

なぜ宣言していないyxのようにconstyまたはの値を変更する必要がありますかx?それがどれほど大きいかarr、そしてあるarr2べきかについて多くの疑問を投げかけるので、うまくいけないでしょう-特に初期化の順序を反映して。(ヒント:それらは定数でなければなりません)
Wyck

--std=c++17(または--std=c++11古いコンパイラの場合)でプログラムをコンパイルすると、コンパイルは失敗します。
einpoklum

回答:


9

どちらの例もC ++では形式が正しくありません。コンパイラが後者を診断しない場合、標準に準拠していません。

なぜここで異なる動作があるのですか?

実行時の長さの自動配列を可能にする言語拡張を使用します。ただし、実行時の長さの静的配列は許可されません。グローバルアレイには静的ストレージがあります。

GCCを使用している場合は、-pedanticコマンドラインオプションを使用して、標準に準拠するように要求できます。移植性の問題について通知を受けるには、そうすることをお勧めします。


4

配列のサイズは定数でなければなりません。これを修正するには、と宣言yconstます。

const int y=5;
int arr[y]; 

これがで機能した理由についてはmain、g ++では拡張機能としてブロックスコープで可変長配列を使用できます。ただし、標準のC ++ではありません。


0

(@eerorikaが言ったように)実行時に自動長さ配列が許可されているため、どちらも使用すべきではありませんが、グローバル配列には静的ストレージが必要です。

可変サイズの配列を宣言する場合(たとえば、std :: cinで指定)、次の行に沿って何かを行います。

int x;
std::cin >> x;
const int n = x;
float arr[n];

しかし、ゼロだけを含むように設定することはできませんfloat arr[n] = {0}(配列の値に追加する必要があり、設定が不明な場合)、そのようなループを使用する必要があります。

for(int i = 0; i < n; i++)
{
    arr[i] = 0;
}

1
あなたの例は、constを使用しているにもかかわらず、まだ正しくありません。サイズはコンパイル時の定数式でなければなりません。もちろん、ランタイム入力から得られるものはそれを満たしていません。
eerorika

「どちらも使用してはならない」という表現は不適切です。可変長配列を使用して移植可能なC ++コードを作成することは避けたいかもしれません。可搬性を犠牲にして、可変長配列を使用して目的のプロジェクト目標を達成したい場合があります。これらの目標の値は主観的であり状況的なものであり、バランスが他の人にとってどこにあるのかは言えません。
Eric Postpischil

@EricPostpischilそのとおりですが、可変変数を使用する場合は変更できます。安全上の理由から、定数として保持することをお勧めします
Jacob Korba

0

C ++の型システムは、これらのCのような配列を、arr2型の例から定義する方法で処理しますint[5]。だから、はい、配列の要素の数は型の一部です!

これは、Cのような配列の定義で使用できるものにいくつかの制約を課します。つまり、この数値には静的ストレージが必要であり、不変であり、コンパイル時に使用可能である必要があります。

したがって、コードを次のようなものに変更すると、別の利点があります。適切な方法で配列を初期化します。

int arr2[] = {0, 0, 0, 0, 0};   
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.