strdup()
Cの関数の目的は何ですか?
10 に答える
まさにそのように聞こえますが、C と UNIX が単語を割り当てる省略された方法に慣れていると仮定すると、文字列が複製されます:-)
これは実際には ISO C 標準自体(a) (これは POSIX のものです) の一部ではないことに注意してください。事実上、次のコードと同じことを行っています。
char *strdup(const char *src) {
char *dst = malloc(strlen (src) + 1); // Space for length plus nul
if (dst == NULL) return NULL; // No memory
strcpy(dst, src); // Copy the characters
return dst; // Return the new string
}
言い換えると:
古い文字列を保持するのに十分なメモリを割り当てようとします (さらに、文字列の終わりを示す '\0' 文字)。
割り当てに失敗した場合は、に設定
errno
され、すぐENOMEM
に戻ります。toNULL
の設定はPOSIXで行うことなので、明示的に行う必要はありません。POSIX に準拠していない場合、ISO C は実際には の存在を義務付けていないため、ここには含めていません(b)。errno
ENOMEM
malloc
strdup
ENOMEM
それ以外の場合は割り当てが機能したため、古い文字列を新しい文字列にコピーし(c)、新しいアドレスを返します (呼び出し元は、ある時点で解放する必要があります)。
それが概念的な定義であることを覚えておいてください。給与に見合ったライブラリ ライターであれば、使用されている特定のプロセッサを対象として、大幅に最適化されたコードを提供している可能性があります。
(a)str
ただし、と小文字で始まる機能は、将来の方向性のために標準で予約されています。からC11 7.1.3 Reserved identifiers
:
各ヘッダーは、関連するサブ条項にリストされているすべての識別子を宣言または定義し、*オプションで、関連する将来のライブラリの指示サブ条項にリストされている識別子を宣言または定義します。**
の今後の方向性についてstring.h
は、以下を参照してC11 7.31.13 String handling <string.h>
ください。
str
、mem
、またはwcs
小文字で始まる関数名は、<string.h>
ヘッダーの宣言に追加できます。
したがって、安全を確保したい場合は、おそらく別の名前にする必要があります。
(b)変更は基本的に次のものに置き換えif (d == NULL) return NULL;
られます。
if (d == NULL) {
errno = ENOMEM;
return NULL;
}
(c)strcpy
意図を明確に示しているので、そのために使用していることに注意してください。memcpy
一部の実装では、データをより大きなチャンクで、または並列に転送できるため、(長さが既にわかっているため) を使用する方が高速な場合があります。そうではないかもしれません :-) 最適化のマントラ #1: 「推測しないで測定する」。
いずれにせよ、そのルートに進むことにした場合は、次のようにします。
char *strdup(const char *src) {
size_t len = strlen(src) + 1; // String plus '\0'
char *dst = malloc(len); // Allocate space
if (dst == NULL) return NULL; // No memory
memcpy (dst, src, len); // Copy the block
return dst; // Return the new string
}
char * strdup(const char * s)
{
size_t len = 1+strlen(s);
char *p = malloc(len);
return p ? memcpy(p, s, len) : NULL;
}
char を再度検索する必要がないため、コードは with よりも少し高速になる可能性があります (すでに with を使用していましstrcpy()
た) 。\0
strlen()
strdup()
他の回答を繰り返す意味はありませんが、C標準の一部ではないため、Cの観点からは何でもできることに注意してください。ただし、POSIX.1-2001 で定義されています。
strdup manから:
このstrdup()
関数は、 が指す文字列の複製である新しい文字列へのポインタを返しますs1
。返されたポインタは に渡すことができますfree()
。新しい文字列を作成できない場合は、null ポインターが返されます。
strdup() は、終了文字 '\0' を含む文字配列に対して動的メモリ割り当てを行い、ヒープ メモリのアドレスを返します。
char *strdup (const char *s)
{
char *p = malloc (strlen (s) + 1); // allocate memory
if (p != NULL)
strcpy (p,s); // copy string
return p; // return the memory
}
つまり、メモリを割り当てなくても、引数で指定された文字列と同じ別の文字列が返されます。しかし、後でそれを解放する必要があります。
渡された文字列のmallocとstrcpyを実行することにより、渡された文字列の複製コピーを作成します。malloc されたバッファは呼び出し元に返されるため、戻り値でfreeを実行する必要があります。
これが行う最も価値のあることは、メモリ (場所とサイズ) を自分で割り当てる必要なく、最初の文字列と同一の別の文字列を提供することです。ただし、前述のように、まだ解放する必要があります (ただし、数量の計算も必要ありません)。
strdup() 関数は、string duplicate の省略形です。パラメーターを文字列定数または文字列リテラルとして受け取り、文字列に十分なスペースを割り当て、割り当てられたスペースに対応する文字を書き込み、最後に割り当てられたアドレスを返します。呼び出しルーチンへのスペース。