8

int main()
{
    const int i = 1.0; // Notice I am assigning a double to an int here
    char a[i];
}

質問

上記のコードをコンパイルしてg++ -O0 -Wall -pedantic -ansi -std=c++11もエラーは発生しません (未使用の変数を除く)。ただし、を削除する-std=c++11と、次の警告が表示されます。

警告: ISO C++ は可変長配列を禁止しています

この SO questionによると、C++03 ではコードが無効であると思います。しかし、誰かが C++11 でルールがどのように変更されたかを説明できますか?

(この質問は、私が回答した以前の質問の結果です。)

4

1 に答える 1

7

バインドされた配列は整数定数式でなければなりません。8.3.4 [dcl.array]/1 を参照してください (C++03 と C++11 で同じ表現):

定数式 (5.19) が存在する場合、それは整数定数式であり、その値は 0 より大きくなければなりません。

C++03 では、整数型にキャストしない限り、整数定数式を浮動リテラルで初期化することはできません。5.19 [expr.const]/1 の最後の文を参照してください。

整数定数式には、リテラル (2.13)、定数式 (8.5) で初期化された整数型または列挙型の列挙子、変数constまたは静的データ メンバー、整数型または列挙型の非型テンプレート パラメーター、およびsizeof式のみを含めることができます。浮動リテラル (2.13.3) は、整数型または列挙型にキャストされている場合にのみ表示できます。

これは、C++03 ではi整数定数式ではないため、バインドされた配列として使用できないことを意味します。

GCC と Clang では C++03 の拡張機能として可変長配列が許可されているため、非定数バインドでコンパイルされますが、-pedantic. 定数の初期化子を整数型にキャストするように変更するとi、有効な整数定数式が作成されます。

const int i = (int) 1.0;

その変更により、配列は可変長ではなくなり、 を使用しても警告はありません-pedantic

C++11 5.19 [expr.const]/3 では、次のように述べています。

リテラル定数式は、リテラル型のprvalue コア定数式ですが、ポインター型ではありません。整数定数式は、整数型またはスコープなし列挙型のリテラル定数式です。

前の (非常に長い) 段落は、コア定数式の規則を説明していますが、基本的に C++11 では、二重初期化子はi、キャストがなくてもコア定数式であることを妨げないため、整数定数式であり、したがって有効です。配列がバインドされているため、警告はありません。

于 2012-06-07T13:41:03.003 に答える