質問

この質問を見る: C/C ++コンパイラがコンパイル時に配列のサイズを知る必要があるのはなぜですか? コンパイラの実装者は、今すぐ足を濡らすために時々(C99標準の一部であり、10年前です)、効率的な実装を提供することができると思いました。

しかし、それはまだ(答えから)費用がかかると見なされているようです。

これはどういうわけか私を驚かせます。

もちろん、静的オフセットはパフォーマンスの点で動的なオフセットよりもはるかに優れていることを理解しています。1つの提案とは異なり、コンパイラにアレイのヒープ割り当てを実行することはありません。測定されました;)

しかし、私はまだ想定されていることに驚いています 費用:

  • 関数にVLAがない場合、私が見ることができる限り、コストはありません。
  • 単一のVLAがある場合、すべての変数の前または後に配置することができ、したがって、スタックフレームのほとんどで静的オフセットを取得できます(または、私には見えますが、スタック管理は十分に容易ではありません))

もちろん、複数のVLAの疑問が生じ、専用のVLAスタックを持つことが機能するかどうか疑問に思っていました。これは、VLAがカウントとポインター(したがって既知のサイズの)で表されることを意味し、この目的でのみ使用されるセカンダリスタックで取得された実際のメモリ(したがって、実際にはスタックも)。

rephrasing

GCC / VC ++でどのようにVLAが実装されていますか?

コストは本当に印象的ですか?

rephrasing

私には、たとえば、使用するよりも優れているようです vector, 、現在の実装でさえ、動的割り当てのコストを負担しないためです(再配置できないというコストで)。

編集:

部分的な応答があります ここ, しかし、VLAを従来の配列と比較することは不公平に思えます。事前にサイズを知っていれば、VLAは必要ありません。同様に、アンドレイトは実装に関していくつかの指針を与えましたが、それは私が望むほど正確ではありません。

役に立ちましたか?

解決

GCC / VC ++でどのようにVLAが実装されていますか?

AFAIK VC ++はVLAを実装していません。これはC ++コンパイラであり、C89のみをサポートします(VLAなし、制限なし)。 GCCがVLAをどのように実装するかはわかりませんが、可能な限り最速の方法は、PointerをVLAへのポインターとそのサイズをスタックフレームの静的部分に保存することです。これにより、一定サイズのアレイのパフォーマンスでVLAの1つにアクセスできます(スタックがx86のように下向きに成長する場合、最後のVLAです[スタックポインター +インデックス*要素サイズ +最後の一時プッシュのサイズ])、そして、最初のVLAが上向きに成長した場合(拒否[stackframe pointer + stackframe + index*ements size))))。他のすべてのVLAは、スタックの静的部分からベースアドレスを取得するためにもう1つの間接を必要とします。

[ 編集: また、VLAを使用する場合、コンパイラはスタックフレームベースポインターを省略できません。これは、コンパイル時間中にスタックポインターからのすべてのオフセットを計算できるため、それ以外の場合は冗長です。したがって、無料のレジスタが1つ少なくなります。 - 編集を終了します ]

コストは本当に印象的ですか?

あまり。さらに、使用しないと、支払いをしません。

[ 編集: おそらくもっと正しい答えは次のとおりです。ヒープ割り当てられたベクトルと比較して、アクセス時間は同じになりますが、割り当てと取引ロケーションはより速くなります。 - 編集を終了します ]

他のヒント

VC ++で実装される場合、コンパイラチームが何らかのバリアントを使用すると仮定します _alloca(size). 。コストは、スタックで8バイトを超えるアラインメントを持つ変数を使用することと同等だと思います(など __m128);コンパイラは、元のスタックポインターをどこかに保存する必要があり、スタックを調整するには、無整合スタックを保存するために追加のレジスタが必要です。

したがって、オーバーヘッドは基本的に追加の間接的であり(VLAの住所をどこかに保存する必要があります)、元のスタック範囲をどこかに保管するために圧力を登録します。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top