1

リストノードを定義するための次の構造体があるとします。

 struct node {
         int            data;
         struct node*   next;
};

そして、私はリストの長さを取得するためにこの関数を持っています:

int Length(struct node* head) {
   struct node* current = head;
   int count = 0;
   while (current != NULL) {
      count++;
      current = current->next;
   }
   return count;
}

なぜ私はこれをしたいのですか:struct node* current = head;頭上で繰り返すのではなく?

だから、なぜこれは大丈夫ではないでしょうか:

int Length(struct node* head) {
   int count = 0;
   while (head != NULL) {
      count++;
      head = head->next;
   }
   return count;
}

長さ関数内に入ると、ヘッドはスコープを失いません。したがって、head = head-> nextを実行しても、関数外では影響を受けませんか?

ありがとう

4

3 に答える 3

4

2つのコードスニペットは同等です。

ただし、潜在的なプログラミングエラーを回避し、読みやすさを向上させるために、関数の引数を変更してはならないという考え方があります(実際には頭を変更していません)。そのために、多くの場合、できるだけ多くの引数を定義している人がいますconst

于 2013-01-16T22:13:27.027 に答える
0

私が知っているプログラマーは、値によって渡される引数の値 (ポインターによって参照されるアドレスなど) が関数全体で変更されないままであると直感的に想定しています。この仮定により、関数を拡張するときに小さなバグを簡単に導入できます。Length関数にデバッグ情報を少し出力したいとします。

int Length(struct node* head) {
   int count = 0;
   while (head != NULL) {
      count++;
      head = head->next;
   }
   printf( "Length of list at %p is %d\n", head, count );
   return count;
}

関数が大きくなればなるほど (またはロジックが工夫されているか、変更を行う人が注意を払っていない...)、この種の問題は発生しやすくなります。

などの短い機能についてはLength、個人的には問題ないと思います(私もそうしています)。

于 2013-01-16T22:41:14.760 に答える
0

とにかく、賢いコンパイラはそれを行います。head はリストの先頭を意味し、 current は単なるイテレータであるため、明確にするためにこれを行う人もいます。これは読みやすさのためです。

于 2013-01-16T22:14:10.937 に答える