5

この回答によると、次のように述べています。

コンパイラは int 型のサイズを認識しているため、適切なアセンブラ命令を生成して、スタック上に foo が存在できるように十分なスペースを確保できます。

コンパイラは、関数を実装するために、関数がスタック上で占有するサイズを知る必要があります。

では、なぜこのコードはコンパイルされるのでしょうか?

int f(int n)
{
    int x[n];
}

int main()
{
    f(3);
    f(5);
    //etc
}

xは整数の配列ですが、そのサイズは一定ではなく、関数が呼び出されるたびに変化する可能性があります。

ここで何が欠けていますか?

4

3 に答える 3

8

これは、標準 C++ の正当なコードではありません。これは、C99 の機能である可変長配列をサポートするコンパイラに固有の拡張機能のおかげでコンパイルされます。

ただし、これは移植可能な C++ではありません。動的なサイズ変更が必要な場合は、関数を次のように書き直すことができます。

#include <vector>

int f(int n)
{
    std::vector<int> v(n);
}

それ以外の場合は、テンプレートにして次のように記述します。

#include <array>

template<std::size_t N>
int f()
{
    std::array<int, N> a;
}
于 2013-04-08T19:38:18.027 に答える
4

非標準の拡張機能を使用しているため、コンパイルされます。厳密には有効な C++ ではありませんが、一部のコンパイラはこれをサポートしています。

あなたの場合(3と5が知られています)、代わりに有効なテンプレートを使用するか、std::vector.

template<int n>
int f()
{
    int x[n];
}

//...
f<3>();
于 2013-04-08T19:38:12.260 に答える
0

この場合、コンパイラの仕事は確かに困難です。実行時に必要なメモリ量 ( n*sizeof(int)) と、そのメモリをどこから取得するかを判断するコードを発行する必要があります。そのメモリは、リリースされる場所と同じ場所で引き続きリリースされるint y[5];ため、その点では何も変わりません。

コンパイラの簡単な解決策の 1 つは、舞台裏のコードをint * __x = malloc(n*sizeof(int)...に変更することですfree(__x)。の一部のコードを書き直す必要sizeof(x)がある場合もありますが、コンパイラは VLA コードを「通常の」コードに書き直すこともできます。魔法は必要ありません。VLA は単なるシンタックス シュガーとして実装できます。

于 2013-04-08T20:21:29.577 に答える