12

VLAとその動作について、明確にする必要のあるいくつかの概念があります。

C99以降のAFIKでは、VLAをローカルスコープに宣言することができます。

int main(int argc, char **argv)
{
    // function 'main' scope
    int size = 100;
    int array[size];
    return 0;
}

ただし、グローバルスコープでは禁止されています。

const int global_size = 100;
int global_array[global_size]; // forbidden in C99, allowed in C++

int main(int argc, char **argv)
{
    int local_size = 100;
    int local_array[local_size];
    return 0;
}

const上記のコードは、修飾子がコンパイル時の値を作成しないため、C99でV​​LAを宣言します。C ++ではglobal_sizeコンパイル時の値であるため、global_arrayVLAにはなりません。

私が知る必要があるのは:私の推論は正しいですか?私が説明した動作は正しいですか?

また、知りたいのですが、グローバルスコープのVLAが許可されないのはなぜですか?CとC++の両方で禁止されていますか?グローバルスコープとローカルスコープへの配列の動作が異なる理由は何ですか?

4

5 に答える 5

12

はい、あなたの推論は正しいです、それはこれらの異なる形式の配列宣言と定義がCとC++によってどのように見られるかです。

const他の人がすでに述べたように、グローバルスコープで真の可変長(非)のVLAを理解するのは困難です。たとえば、長さの式が別のコンパイル単位のオブジェクトを参照する場合、評価の順序はどうなりますか?C ++にはVLAはありませんが、ファイルスコープでオブジェクトを動的に初期化できます。そして、評価の順序に頼らなければならない場合、すでにこれはあなたにかなりの頭痛の種を与えます。

constこれにより、修飾されたオブジェクトを含む長さ式に関してCに小さなギャップが残りますが、これは許可されていません。これは、そのようなオブジェクトがC標準では「整数定数式」と見なされないという事実に由来します。これは将来のバージョンで変更される可能性がありますが、これまでC委員会は、そのようなことを許可する必要はないと考えてenumいました。Cでその役割を果たす定数があります。唯一の制限はint、Cで制限されることです。それらもあるといいでしょうsize_t

于 2012-12-28T23:22:46.373 に答える
4

C++ は VLA をサポートしていません。2 番目のコード スニペットが C++ で機能する理由は、constキーワードが C++ でコンパイル時の定数を作成するためです。Cではそうではありません。

C99 は、サイズ変数の宣言方法に関係なく、ブロック スコープ、ピリオド外の VLA をサポートしません。C2011 では VLA サポートがオプションになっていることに注意してください。

于 2012-12-28T20:37:14.420 に答える
3

禁止されていることと許可されていないことには違いがあります。;-)

VLA 機能は、ローカル配列にスタック領域を使用できるように設計されており、ヒープ割り当てに malloc を使用する必要がありません。これは主に速度の最適化です。

ここで、関数の外部で VLA を使用したいと考えています。なんで?プログラムの開始時に malloc 呼び出しを 1 回だけ回避することで、スピード的に勝てる点はあまりありません。また、静的な寿命を持つ変数には、どのスタック スペースを使用すればよいのでしょうか?

于 2012-12-28T20:29:36.667 に答える
3

基本的な理由は、グローバル変数にリンケージがあり、そのサイズをコンパイル時に知る必要があるためだと思います。そうでない場合、どうすればプログラムをリンクできますか?

ローカル変数にはリンケージがなく、VLA はスタックに割り当てられ、プログラムの実行に伴って動的に増加します。

于 2012-12-28T20:37:08.797 に答える
0

したがって、グローバル VLA の場合、問題の 1 つ (テーマには多くのバリエーションがあります) をここに示すことができます。

int size;
int a;
int v[size];
int b;

....別のファイルで:

extern int a;
extern int b;

リンカーは、リンク時に a と be が相互に関連する場所を認識している必要があります。そうしないと、ロード時にそれらを正しく修正できません。

于 2012-12-28T21:08:22.350 に答える