strdup()
C の関数の目的は何ですか?
strdupa
strlen
非常に小さいと判断していない限り、危険ですので使用しないでください。ただし、スタック上で固定サイズの配列を使用するだけで済みます。
strdup
/はstrdupa
どういう意味ですか?
strdup()
C の関数の目的は何ですか?
strdupa
strlen
非常に小さいと判断していない限り、危険ですので使用しないでください。ただし、スタック上で固定サイズの配列を使用するだけで済みます。
strdup
/はstrdupa
どういう意味ですか?
回答:
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
、NULL
すぐに戻ります。設定errno
にはENOMEM
何かであるmalloc
私たちは、明示的に私たちにそれを行う必要はありませんので、POSIXでありませんstrdup
。POSIXに準拠していない場合、ISO Cは実際にはの存在を義務付けていないENOMEM
ため、ここには含めません(b)。
それ以外の場合は割り当てが機能したため、古い文字列を新しい文字列(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
}
strdup
は、文字列コピーにヒープメモリを割り当てる必要がある状況向けです。それ以外の場合は、自分で行う必要があります。あなたは既に場合は持って十分な大きさのバッファ(そうでmallocまたは)を、はい、使用strcpy
。
{ EDOM, EILSEQ, ERANGE }
必須のエラーコードとしてのみ義務付けています。これを説明するために回答を更新しました。
char * strdup(const char * s)
{
size_t len = 1+strlen(s);
char *p = malloc(len);
return p ? memcpy(p, s, len) : NULL;
}
たぶん、コードが少し速くよりもあるstrcpy()
よう\0
charが(それはすでにしていた再検索する必要はありませんstrlen()
)。
return memcpy(malloc(len), s, len);
ではなく、割り当てのクラッシュを好むので NULL
。
NULL
はクラッシュする必要はありません。未定義です。確実にクラッシュするようにしたい場合emalloc
はabort
、失敗時にコールするを記述します。
emalloc
SolarisやLinuxでは必要ない場合でも使用する習慣をつけて、将来他のプラットフォームでコードを作成するときに使用できるようにします。
他の答えを繰り返すstrdup()
意味はありませんが、C標準の一部ではないため、Cの観点からは何でもできることに注意してください。ただし、POSIX.1-2001で定義されています。
strdup()
ポータブル?いいえ、非POSIX環境では使用できません(とにかく簡単に実装できます)。しかし、POSIX関数が何でも実行できると言うのはかなり面倒です。POSIXは、Cと同じくらい優れた、さらに人気のあるもう1つの標準です。
strdup
も、拡張機能として機能を提供できるということです。そのような実装では、それがstrdup
POSIX関数と同じように動作するという保証はありません。そのような実装については知りませんが、悪意のない正当な実装がchar *strdup(char *)
歴史的な理由で提供され、を渡す試みを拒否する可能性がありますconst char *
。
strdup manから:
strdup()
この関数はが指す文字列のコピーである新しい文字列へのポインタを返しますs1
。返されたポインタはに渡すことができますfree()
。新しい文字列を作成できない場合は、nullポインタが返されます。
strdup
およびstrndup
POSIX準拠のシステムで次のように定義されます。
char *strdup(const char *str);
char *strndup(const char *str, size_t len);
strdup()関数は、文字列のコピーのための十分なメモリを割り当てstr
、コピーを行い、それへのポインタを返します。
その後、ポインタは関数の引数として使用できますfree
。
メモリが不足している場合NULL
はが返され、errno
に設定され
ENOMEM
ます。
strndup()高々機能をコピーしlen
た文字列から文字がstr
常にコピーされた文字列をヌル。
ステートメント:
strcpy(ptr2, ptr1);
これは(これがポインターを変更するという事実を除いて)以下と同等です:
while(*ptr2++ = *ptr1++);
一方:
ptr2 = strdup(ptr1);
以下と同等です。
ptr2 = malloc(strlen(ptr1) + 1);
if (ptr2 != NULL) strcpy(ptr2, ptr1);
したがって、コピーした文字列を別の関数で使用する場合(ヒープセクションで作成されるため)、を使用できますstrdup
。それ以外の場合strcpy
は十分です。
strdup()関数は文字列複製の省略形であり、文字列定数または文字列リテラルとしてパラメーターを受け取り、文字列に十分なスペースを割り当て、割り当てられたスペースに対応する文字を書き込み、最後に割り当てられたアドレスを返します呼び出しルーチンへのスペース。
strdup
は文字列定数である必要はありません。それはC文字列でなければなりませんchar
。