1

2 つの連結リストの実装 ( queue.h [ source ] とutlist.h [ source ]) を検討していますが、それぞれの実装に関していくつか質問があります。

  1. _Q_INVALIDATEqueue.hとは何ですか? デバッグの一部だと思いますが、マクロdefineロジックがよくわかりません。
  2. 両方の実装で と が提供されFOREACHますFOREACH_SAFE。前者は単純明快ですが、後者の背後にあるロジックは何ですか? また、前者がとにかく安全でない場合、そもそもなぜそれが実装されたのですか?
  3. と(と)queue.hの型が異なる構造体を実装したのはなぜですか?nextprevstruct *le_nextstruct **le_prev
  4. 両方の実装で、あちこちに余分な括弧が挿入されているのはなぜですか? 例えば。周りhead#define LIST_FIRST(head) ((head)->lh_first)
4

1 に答える 1

4

質問 1 の場合:

_Q_INVALIDATEの値に使用されなくなったポインターを設定するマクロです-1。その意図は、ポインターを使用するとすぐにクラッシュが発生するため、後で使用するとデバッグが容易になることです。非デバッグ モードでは、マクロは何もしないので、ポインターは現在の値のままになります。ポインターが使用される原因となるバグがある場合、問題ははるかに微妙な欠陥である可能性があります。

質問 2 の場合:

これらのマクロの「安全な」バージョンは、現在のアイテムが処理されている間にリスト内の次のアイテムを指すためにマクロが内部的に使用する追加のポインター引数を取ります。これにより、ループ内のコードで現在の項目をリストから削除できます。次の項目は既に一時ポインターに記憶されているため、マクロは次の反復のために問題なくそれを取得します。マクロの安全でないバージョンは一時ポインターを使用しないため、反復中にリストから現在の項目を削除することはできません。

質問 3 の場合:

これにより、現在の要素の前に新しい要素を追加したり、現在の要素がリストの先頭にあるか (したがって、リスト ポインターによってのみ「指されている」か) を気にせずに、現在の要素をリストから削除することが容易になります。現在の要素がリストの他の場所にある場合 (したがって、別の要素のle_nextポインターによって指されている場合)。の場合、リストの最初の要素を処理するにle_prevstruct type*、特別なケースのコードが必要になります。le_prevは であるため、(各要素のリンクのように)内部の任意のオフセットに埋め込まれた と同じくらい簡単に (リスト ヘッド ポインタのような)struct type**単純なものを参照できます。struct type*struct type*typele_next

質問4は上記のコメントで回答されました。

于 2013-05-17T08:17:47.570 に答える