GCCおよび可変長配列

クラスメイトが何らかのエラーとC ++コードを送信し、これに関するコンパイラー出力がありました。 しかし、私が最も驚いたのは彼の問題ではなく、コンパイル段階で長さが不明な配列がコードのスタックに作成されたという事実でした。 私はこれに出会った言語を学び始めたときに覚えており、これは行われるべきではないことに気づいた。 奇妙ですが、クラスメートのコンパイラは他のエラーを生成しませんでした...

私はどこかで次のC ++ 14標準がそのようなトリックを許可するかもしれないと読んだ。 しかし、実際の配列では、配列のサイズは定数式でなければなりません。 これにより、VLAが長い間利用されてきたC99との互換性が再び低下します。

GCC 4.8.1を使用しているので、確認することにしました。
void foo( int n) { int array[n]; } 

-pedanticオプションを指定したコンパイラは、正直に返されました。
警告:ISO C ++は可変長配列 'array'を禁止しています。

実際、gccのC ++のVLAは拡張機能です。

最も重要なことは、sizeof演算子は、計算時間ではなく実行時の可変長配列のサイズを考慮することです。 したがって、たとえば、sizeof(vla)を使用して、型以外のパラメーターでテンプレートをインスタンス化することはできません。
 template <int p> class A { }; void foo(int length) { int const_lenght_array[7]; int variable_length_array[length]; A<sizeof(const_lenght_array)> a1; //OK A<sizeof(variable_length_array)> a2; //ERROR } 

コンパイラエラーメッセージは、実行時に配列サイズがどのように計算されるかを適切に答えます。
エラー: '(unsigned int)(((((sizetype)(((ssizetype)length)+ -1))+ 1u)* 4u)'は定数式ではありません

可変長とtypedefの配列へのポインターを使用することもできます。
 int (*p)[length] = &variable_length_array; typedef int variable_int_array_t [length]; 

何よりも、GNU拡張機能を使用すると、可変長配列の可変長配列を作成できます。これは、トップレベルのみが可変長を持つことができる新しい場合でも許可されていません。
 void bar(int a, int b) { int auto_array[a][b]; //OK int (*dynamic_array)[b] = new int[a][b]; //ERROR } 

幸いなことに、VLAはC ++ 14で導入されますが、この拡張機能とC99のVLAとはほとんど互換性がありません。 少なくともsizeofとtypedef / using(c ++ 11)の形式は正しくありません。 これにより、熊手を踏むことなく、sizeofからのコンプライアンス動作のみを期待できます。 以下は、gccのパッチへのリンクです。

C ++のVLAは役に立たなくなっていると多くの人が考えていることを知っています。そのような目的のためにベクトルがあり、メモリが要素に実際に割り当てられる場所を気にしません。 それでも、この記事の目的は、後で驚くことのないように、gccでそのような機会を示すことでした。
結論として、open-stdでのVLAの提案

Source: https://habr.com/ru/post/J195148/


All Articles