2012-01-25 19 views
4

私はどちらを使うべきかを決めようとしています。構造体の配列と構造体へのポインタの配列の賛否両論は何ですか?

私の頭の上から考えることができる構造へのポインタの賛成論。

  • アレイのすべての要素を使用しないと、スペースが無駄になりません。
  • 少ない傍受両側のための配列要素

その他のプロの/詐欺のスワッピング?

+0

あなたの要件は何ですか?コンパイル時に配列にいくつの要素があるのか​​知っていますか?配列内の要素の交換頻度はどれくらいですか?どのような重大さがどのくらい重くなってコピーのパフォーマンスが問題になるのでしょうか? – Naveen

+1

この質問はあまりにもあまりにも曖昧ではありません。答えは本質的に「Cで学ぶプログラム」の全体の章です。これは、プリンタを買うことと、モニターを買うことの賛否両論について質問することと同じです。どちらも出力がありますが、それらは異なっています。 –

+0

@KerrekSBそしてどちらの状況で相違点が何であるか尋ねると何が問題になりますか?私はこれらの答えが有用であることを発見しました、そして、私は将来、疑問を持っている他の人も同様に望みます。 – Michael

答えて

5

これらのアプローチのいくつかの他の違いがあります:

  • は、アレイ・オブ・ポインタのアプローチは、配列のサイズを変更するには、オーバーヘッドを削減。
  • ポインタ配列のアプローチでは、空の/未使用の値(NULL)が得られます。これがアプリケーションで意味的に有効な場合は、これが利点です(これを表現するにはstruct自体を変更する必要はありません)。
  • 配列のポインタのアプローチでは、配列の複数の要素がコピーではなく同じstructを参照することができます。この状況がアプリケーションにとって意味論的に合理的である場合も、これは利点に過ぎません。
  • アレイの構造のアプローチは、より多くの局所性を提供します(配列内で近接しても近接してメモリ内に接近しますが、状況によってはパフォーマンス上の利点があります)。
  • 非常に多数のアイテムの場合、構造体配列のアプローチには大きな連続したメモリブロックが必要です。プロセスアドレス空間が断片化している場合は、利用できない可能性があります。
4

一般に、ポインタの配列、またはポインタを使用することの欠点は、次のとおり

ポインタは(ほとんど)動的メモリ割り当てを使用することを含むであろうし、それは、このダイナミックメモリを手動で管理することを意味します。
動的メモリ割り当ては、スタック割り当てよりも少し遅くなります。
また、ダイナミックメモリを使用すると、使用エラーが発生しやすくなります。

は、そのいずれかを選択するためには、実際に依存する、と述べた:

  • あなたは構造体を交換する必要がありますどのくらいの頻度
  • コンパイル時に知られている必要な構造の数はどのようかさばるあなたの構造をされています
+4

Downvoter:downvoteを説明するか、匿名で行うことによってdownvoteへのあなたの権利を悪用することを控えてください。 –

+0

+1を補正する –

+0

動的メモリは、あなたが何をしているのかを知っていれば、遅くなく、エラーが発生しにくいという2つの理由があります。静的および動的メモリにはそれぞれ独自の落とし穴があります。 –

1

可能な限りの理由は、ポインタを使って作業することはプログラマにとってオーバーヘッドになることです。プロジェクトの目標を決める必要があります。

ソートやスワッピングをたくさん行う予定がなく、メモリが十分にあり、それを最大限に活用する予定がない場合は、ポインタを使用する頭痛があるのか​​どうか自問自答する必要があります。

+0

私は、単に12要素の配列を扱っていても、可能な限り最も難しい方法を常に実行すべきだと考えていると思いますか?詳しく説明しますか? – jmort253

2

データをディスクに書き込むか、ソケットで送信するか、共有メモリ(組み込みのリアルタイムアプリケーションのすべての非常に一般的なタスク)に配置する必要がある場合は、配列を少しシンプルにすることができます。

アレイはmalloc().の使用を避けますが、アレイが大きく、メモリスペースが断片化していると、cafが指摘するように問題が発生することがよくあります(realloc(),)。もちろんrealloc().bss,または.text.の配列には適用されません。私は他の答えを楽しみにしています。良い質問。

+0

'realloc'は' malloc'を介して割り当てられたダイナミックメモリのためのものであり、スタックや静的に割り当てられたメモリに宣言された配列のものではありません。 – Jason

+0

Alsのように、私はちょうど奇妙なdownvoteを受け取りました。私はこれが世界で最も魅力的な答えではないかもしれないことに同意するが、来る... –

+0

@ Jason:良い警告。 '.bss '、afaikを拡張することはできません。私は誰も' realloca() '関数を望んでいないことを願っています! –

3

ここで重要な違いがあります。構造体の配列にはsizeof(struct)* nサイズの連続したメモリブロックが必要ですが、構造体へのポインタ配列は必要ですが、それでも連続したメモリが必要です配列自体のために、それぞれの構造が必ずしも隣り合っている必要はないので、前者は大きなメモリブロックを必要とし、後者はより多くの断片化をもたらします。

また、構造体の配列をディスクに書き込む方が簡単だと言われていますが、最初の要素とsizeof(struct)* nのポインタを使ってwriteを一度呼び出すだけで済むので、ポインタの配列を使用して、各要素をループして個別に書き込む必要があります。

編集:ループの各構造体にポインタの配列を割り当てる必要があります。お役に立てれば。

1

ポインタの配列には、ポインタと構造体を格納するスペースが必要です。一方、異なる構造体が意味のあるデータの量は変わらないが、構造体へのポインタを使用すると、異なる量の領域を割り当てることができます。これによりスペースを節約することは、余分なポインタのコストを上回る場合もあります。

構造体にアクセスするためのポインタの配列を使用すると、多くの場合、構造体の配列ごとに追加のテーブル参照が必要になります。多くの新しいアーキテクチャーでは、乗算はテーブルルックアップよりも安価ですが、一部の小規模またはそれ以上のアーキテクチャーではその逆が成り立ちます。また、一部の小規模または古いアーキテクチャでは、特定のメモリ境界にまたがるオブジェクトでは問題が発生することがあります。 80バイトを超える配列を割り当てることが不可能なアーキテクチャであっても、8つの20バイト構造体ポインタの配列を割り当てることは可能です。

関連する問題