0

私は自分の文字列コピー関数を書いています。次の作品:

char *src, *dest;
src = (char *) malloc(BUFFSIZE);
//Do something to fill the src
dest = (char *) malloc(strlen(src) + 1);
mystringcpy(src, dest);

void mystringcopy(char *src, char *dest) {
   for(; (*dest = *src) != '\0'; ++src, +dest);
}

しかし、これは機能しません:

char *src, *dest;
src = (char *) malloc(BUFFSIZE);
//Do something to fill the src
mystringcpy(src, strlen(src), dest);

void mystringcopy(char *src, size_t length, char *dest) {
   dest = (char *)malloc(length + 1);
   for(; (*dest = *src) != '\0'; ++src, +dest);
}

理由がわかりません...呼び出された関数内にメモリを割り当てるのは間違いですか?

4

5 に答える 5

2

「機能する」とはどういう意味かは実際には言っていませんがdest、呼び出し元の関数で新しいメモリに変更されない理由が混乱していると思います。

その理由は、mystringcopy関数では、パラメーターdestが呼び出し元の関数のポインターのコピーであるためです。dest

次に、そのコピーを新しいバッファに割り当て、コピーを実行すると、コピーが消えます。オリジナルは変更されていません。destポインタとして(ポインタに)渡す必要があります。

また、メモリから行ったことをそのままではコンパイルできないため、メモリから書き込んだと思います(呼び出し元の関数での間接参照が不適切です)。修正されたコードは次のとおりです。

char *src, *dest;
src = (char *)malloc(BUFFSIZE); // no dereference on src, it's a pointer

//Do something to fill the src
mystringcpy(src, strlen(src), &dest); // pass the address of dest

// take a pointer to a char*
void mystringcopy(char *src, size_t length, char **dest) {
    // now you should dereference dest, to assign to
    // the char* that was passed in
    *dest = (char *)malloc(length + 1);

    // for simplicity, make an auxiliary dest
    char* destAux = *dest;

    // and now the code is the same
    for(; (*destAux = *src) != '\0'; ++src, ++destAux);
}

dest別の方法は、ポインタを返すことです。

char *src, *dest;
src = (char *)malloc(BUFFSIZE);

//Do something to fill the src
dest = mystringcpy(src, strlen(src)); // assign dest

char* mystringcopy(char *src, size_t length) {
    char* dest = (char *)malloc(length + 1);

    // for simplicity, make an auxiliary dest
    char* destAux = dest;

    for(; (*destAux = *src) != '\0'; ++src, ++destAux);

    return dest; // give it back
}

長さがソースバッファの実際の長さよりも短い場合は、デスティネーションバッファをオーバーランすることに注意してください。解決策についてはコメントを参照してください。ただし、これはあなたに任されています。

于 2010-01-29T19:21:48.433 に答える
2

関数内での割り当ては問題ありません。

問題は、Cでは引数が値で渡されることです。したがって、destに値を割り当てる場合、それは関数に対してローカルのdestを変更するだけです。

2つの選択肢があります。destポインタを返すことができます:

char *alloc_and_copy(const char *src, size_t length)
{
    char *dest = malloc(length + 1);
    ... do your copying
    return dest;
}

または、引数へのポインタを渡して、ポイントされているものを変更することもできます。

void alloc_and_copy(const char *src, size_t length, char **dest)
{
    char *local_dest = malloc(length + 1);
    ... do your copying using local_dest

    *dest = local_dest;
}

ローカル変数を使用する手法は必須ではありませんが、コードが読みやすくなると思います。

于 2010-01-29T19:21:58.327 に答える
2

関数内でmallocを実行することは問題ありませんが、関数からポインターを戻すことはありません。ポインタを返します。

char * mystringcopy(char *src)

または、ポインタをポインタに渡します。

void mystringcopy(char *src, char **dest)
于 2010-01-29T19:22:05.297 に答える
2

Cのパラメーターは値で渡されるため、関数はdestポインターのコピーを取得し、それを上書きしてmallocから破棄します。代わりにこれを試してください:

void mystringcopy(char *src, size_t length, char **dest) {
   *dest = (char *)malloc(length + 1);
   char *p=*dest;
   for(; (*p = *src) != '\0'; ++src, ++p);
}

ここで、文字列へのポインタへのポインタを渡すので、メインプロシージャで上書きできます。あなたはそれを次のように使うでしょう:

char *src, *dest;
*src = (char *) malloc(BUFFSIZE);
//Do something to fill the src
mystringcpy(src, strlen(src), &dest);
// now in dest you have your copy
于 2010-01-29T19:23:20.223 に答える
1

一般に、メモリを割り当てるときは、メモリの解放が完了したときにどのコードがメモリを解放するのかについて特定の仮定があります。私は、関数がブラックボックスのように1つの主要な操作を担当する必要があるという概念に同意します。両方の理由から、独自のメモリを割り当て、関数へのポインタを渡してそのバッファにデータを取り込むのが最善です。

char *それはさておき、ポインタを戻り値として返すこともできます。

または、char *destパラメータをに変更しますchar **dest。次に、次のような関数を呼び出しますmystringcopy(src, strlen(src), *dest)。そして、関数では、次のようにしてポインタを返します*dest = (char *)malloc(length + 1);。きれいではありません。

于 2010-01-29T19:23:11.443 に答える