以下は、おそらくあなたが探しているよりもはるかに多くの情報になるでしょう. 今すぐすべてを吸収することについてあまり心配する必要はありませんが、後で必要になる可能性があります。
まず、用語に関する重要な注意事項です。C には「文字列」型はありません。ISO C標準を引用:
文字列は、最初の null 文字で終了し、最初の null 文字を含む連続した文字列です。[...]文字列へのポインターは、最初の (アドレス指定が最も低い) 文字へのポインターです。
特に、char*
値は文字列ではなくポインターです (通常、文字列char*
へのアクセスと操作にはポインターを使用します)。配列は文字列を含むことはできますが、それ自体は文字列ではありません。
(比較的単純な)関数の場合、char*
返す値は文字列リテラル(の最初の文字)を指しているため、メモリ管理は問題になりません。より複雑なケースでは、この言語は率直に言って特に役に立たず、自分でメモリを管理するために何らかの作業を行う必要があります。
char*
関数は文字列を指す値を簡単に返すことができ、呼び出し元はその文字列を好きなように処理できますが、その文字列を構成する文字はどこに格納されているのでしょうか?
(少なくとも) 3 つの一般的なアプローチがあります。
(1) 関数は、次の静的配列の先頭へのポインターを返しますchar
。
char *func(void) {
static char result[100];
// copy data into result
return result;
}
これは機能しますが、いくつかの欠点があります。配列のコピーは 1 つしかなくresult
、連続してfunc()
を呼び出すと、その配列の内容が破壊されます。また、配列のサイズは固定です。返すことができる最大の文字列を保持するのに十分な大きさである必要があります。標準 Casctime()
関数はこのように機能します。
(2) 呼び出し元は文字列へのポインターを渡し、関数にそれを入力させることができます。
void func(char *buffer) {
// code to copy data into the array pointed to by buffer
}
これは、 の配列を割り当てなければならない呼び出し元に負担をかけ、char
特に必要な大きさを知る必要があります。
(3) 関数は、次を使用して文字列にメモリを割り当てることができますmalloc()
。
char *func(void) {
char *result = malloc(some_number);
if (result == NULL) {
// allocation failed, cope with the error
}
// copy data into the array pointed to by result
return result;
}
これには、割り当てる必要があるメモリの量を関数が決定できるという利点があります。ただし、呼び出し元は、文字列がヒープに割り当てられていることを認識している必要があるため、後で を呼び出して解放できますfree()
。malloc()
and関数も比較的高価になる可能性があります(free()
ただし、プログラムのパフォーマンスが十分でないことが確実でない限り、心配する必要はありません)。
実際には、4 番目の方法がありますが、それは間違っています。
char *bad_func(void) {
char result[100];
// copy data into result
return result; // equivalent to "return &result[0];"
}
ここでの問題は、result
が関数に対してローカルであり、 として定義されていないstatic
ため、関数が戻るとすぐに配列オブジェクトが存在しなくなることです。呼び出し元は、予約されていないメモリへのポインタを受け取り、背後で再利用できます。ローカル オブジェクトへのポインターを返すことはできstatic
ます (単一のコピーがプログラムの存続期間中に存在するため)。ローカルの非オブジェクトの値を返すことはできますが、ローカルの非オブジェクトのアドレスをstatic
安全に返すことはできません。物体。static
comp.lang.c FAQは優れたリソースです。