1

array of floatslikeを定義すると、次のようになるのはなぜですか。

const int i[] = { 1, 2, 3, 4 };
float f[i[3]]; // Illegal

関数の外側 (つまり、グローバル) でこれを行うことは違法です。一方、次のような関数( main() を含む)内で同じことを行う場合:

void f() {
    const int i[] = { 1, 2, 3, 4 };
    float f[i[3]];
    cout << sizeof(f);
}

main()
{
    f();
}

その後、すべてが正常に機能し、サイズが 16 として正常に出力されます。この違いはなぜですか?格納場所が static (当初) から stack に変更されたためですか?

(PS: C++ では、コンパイル時に値がわからない変数を使用して配列を定義できないことはわかっていますが、それでも関数内でどのように機能しますか?)

4

2 に答える 2

3

デフォルトでは、標準への厳密な準拠を指定しない場合、多くの場合、コンパイラは C の機能を C++ で使用できるようにします (逆も同様です)。GCC と Clang の両方で、そのような C99 機能、つまり VLA をデフォルトで使用できます。(Visual Studio、OTOH は C モードでも VLA をサポートしていません。) ただし、VLA はブロック スコープでのみ定義できることに注意してください。

6.7.6.2 配列宣言子

2 識別子が可変的に変更された型を持つと宣言されている場合、それは通常の識別子 (6.2.3 で定義) であり、リンケージを持たず、ブロック スコープまたは関数プロトタイプ スコープのいずれかを持つ必要があります。識別子が静的またはスレッド ストレージ期間を持つオブジェクトとして宣言されている場合、可変長配列型を持たないものとします。

そのため、グローバル VLA は C++ では (緩いコンパイラ設定では) 機能しませんが、関数ローカル VLA は機能します。

以下をコンパイルしてみてください

$ cat float.cpp
int main() {
  int i = 2;
  const float f[i] = { 1, 2 };
}

とするg++ -std=c++98 -Wall -ansi -pedantic float.cppと、次のようなものが得られます。

float.cpp: In function 'int main()':
float.cpp:3:18: warning: ISO C++ forbids variable length array 'f' [-Wvla]
float.cpp:3:29: error: variable-sized object 'f' may not be initialized
float.cpp:3:15: warning: unused variable 'f' [-Wunused-variable]
于 2012-06-07T07:42:57.437 に答える
2

C++11 はこれを許可します:

#include <iostream>

constexpr int i[] = {1,2,3,4};
float k[i[2]];

int main()
{
  std::cout << sizeof(k) << "\n";
}

そして形が整ってきます。

最初の質問に関しては、これはおそらく G++ 拡張機能です。

于 2012-06-07T07:41:46.690 に答える