0

私はcとポインターに非常に慣れていません。理解したと思うたびに、よくわからない問題が発生します (c ドキュメントを読むのに時間を費やしましたが、ポインターはまだ不明なままです)。

typedef struct {
        int q[QUEUESIZE+1];
        int first;
        int last;
        int count;
} queue;

enqueue(queue *q, int x)
{
  if (q->count >= QUEUESIZE)
        printf("Warning: queue overflow enqueue x=%d\n",x);

  else {
    q->last = (q->last+1) % QUEUESIZE;
    q->q[ q->last ] = x;
    q->count = q->count + 1;
  } 
}

私の質問が不透明になりすぎないことを願っていますが、誰かがエンキュー関数でのポインターの使用について説明できますか? キューイングの原理は、正確な連続したメモリアドレスを割り当てることだと思っていましたが、そうではありません....

4

2 に答える 2

3

enqueueキューキュー(タイプqueueのキュー)を取り、その中に要素(整数で構成されている)を追加します。

queue *qおそらく、ポインタです

  • 複数のキューが存在する可能性があり、パラメーターは、話しているキューを示します
  • グローバル変数を回避するために、キューはパラメーターとして指定されます。キューへの参照が必要です。これにより、キューを変更でき、終了後も変更が有効になります。enqueue

次のように、値でキューを渡す

enqueue(queue q, int x) { ...

を意味します

  • パラメータとして指定された大量のデータ(キューmyqueueのqパラメータへのコピー)
  • が変更されると、関数内でq変更が行われます。パラメータとして最初に提供されたキュー(myqueue)は変更されませんqenqueue

例えば

enqueue(queue q, int x) { 
  q.count++; // only the local q.count is changed, not myqueue.count
  // ...
}

// ...

queue myqueue;
// ...
enqueue (myqueue, 3); // enqueue changes its local parameter, myqueue is not affected

さらに、enqueue関数の実装を最適化することができます...(より良いキューの実装を提案する以下のwildplasserの回答を参照してください)

于 2013-02-03T16:14:24.940 に答える
1
struct queue {
        unsigned first;
        unsigned count;
        int q[QUEUESIZE];
        };

int enqueue(struct queue *q, int x)
{
  if (q->count >= QUEUESIZE) {
        fprintf(stderr, "Warning: queue overflow enqueue x=%d\n", x);
        return -1;
        }

  q->q[ (q->first+q->count++) % QUEUESIZE ] = x;
  return 0; /* success */ 
}

いくつかのポイント:

  • 診断出力は stderr に送られるべきです
  • カウントとオフセットに符号なしの型を使用すると、(ほとんどの場合) 数値のアンダーフローが回避されます (またはオーバーフローに変換され、より速く失敗します ;-)
  • {head, tail, count} の 3 つの要素は必要ありません。2 つの {head, count} だけで十分です。
  • 変数が少ない := 代入が少ない := 行数が少ない = エラーの可能性が少ない。
  • 範囲チェックとモジュロ除算の QUEUESIZE は、sizeof q->q / sizeof q->q[0]より堅牢な に置き換える必要があります。
于 2013-02-03T16:28:43.210 に答える