2

トリミングに関するウィキペディアの記事を読んでいて、このltrimの実装を見ました(左トリム)

char *
ltrim(char *str)
{
  char *ptr;
  int  len;

  for (ptr = str; *ptr && isspace((int)*ptr); ++ptr);

  len = strlen(ptr);
  memmove(str, ptr, len + 1);

  return str;
}

memmove をスキップして ptr ではなく返すと、悪いことが起こりますか?

char *
ltrim(char *str)
{
  char *ptr;
  int  len;

  for (ptr = str; *ptr && isspace((int)*ptr); ++ptr);

  return ptr;
}
4

2 に答える 2

7

ptr元のポインター以外のポインター値を返す場合、そのポインターが元のメモリ ブロックへの唯一のポインターである場合、誰もそれを返すことができずfree()、メモリ リークが発生します。割り当てられたブロックの途中へのポインタを呼び出すことはできませんがfree()、ブロックの先頭へのポインタのみ、つまり によって最初に返されたポインタのみを呼び出すことができますmalloc()

何らかの理由で、元のブロックへのポインターが保持されるか、ブロックを解放する必要がないことが確実な場合は、memmove()必要ありません。しかし、これらは汎用のユーティリティ ルーチンとしては不適切な仮定です。

于 2012-07-09T19:19:25.413 に答える
3

最大の問題:これはltrim()期待される動作方法ではありません。

ltrim()文字列を所定の位置に変更するという副作用が予想されます。

例えば、

char *a = " hello";
trim(a);
printf(a);

を印刷することが期待されます"hello"が、それなしmemmove()では印刷されません。

追加するために編集:

以下のコメントは、「誰に期待されていますか?」と合理的に尋ねています。

自動ガベージ コレクションを備えた言語では、文字列関数が目的の変換を行った新しい文字列を返すことを期待しています。

それがない場合(ここではそうです)、文字列をその場で変更し、結果へのポインターを返すこともあれば、返さないこともあると思います。

したがって、おそらく私はこう言うべきでした:これは C 関数が期待される方法ではありません。

于 2012-07-09T19:56:42.660 に答える