2

よくわからないC文字列の問題を手伝ってくれないかと思っていました。3文字のポインタを送信する関数があります。この関数内で、charポインターはシフトされ、正しく変更されます。ただし、それらが呼び出されたメイン関数に戻ると、上記の関数は変更されません。私は価値を渡すのは間違いですか?これが私のコードの例です:

int main(void) 
{ 
    LPSTR path = (char*)malloc(strlen(START_PATH));

    strcpy( path, START_PATH );

    char* newstr = (char*)malloc(PATH_SIZE);

    TrimVal(path, "*.*", newstr);

    //Do Stuff

    return 0;
}

void TrimVal(char* modify, char* string, char* newstr)
{ 
      newstr[0] = '\0';

      modify = strncat(newstr, modify, (strlen(modify) - strlen(string)));

      return;
}      

注:PATH_SIZEはサイズ値でありSTART_PATH、char配列であると想定します

4

7 に答える 7

6

こうすることで

 modify = strncat(newstr, modify, (strlen(modify) - strlen(string)));

ポインターが指すものではなく、ポインターを変更しています。

pathTrimValに渡すとき。pathたとえば、0x12345のメモリ位置に渡されます

あなたが言っていることをするときmodify =、ローカル変数modifyを新しいメモリ位置に変更してください、例えば 0x54321

main に戻ると、0x12345 へのポインタしかなく、そこを見ると何も変わっていません。

あなたは簡単にあなたの問題を解決することができます

{ 
...
TrimVal(&path, "*.*", newstr);
... 
}

void TrimVal(char** modify, char* string, char* newstr)
{ 

      newstr[0] = '\0';

      *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string)));

      return;

}    
于 2009-10-15T15:24:26.007 に答える
1

このスレッドで提起された他の多くの優れた点に加えて、いくつかの点があります。

    LPSTR path = (char*)malloc(strlen(START_PATH));

これがCの場合、の戻り値をキャストしないでくださいmalloc。(CFAQ7.7bを参照してください。

さらに重要なことに、その計算strlenには終了が含まれていません。\0したがって、をpath指すメモリは、保持するのに必要なメモリ量にSTART_PATH加えて、 1文字不足してい\0ます。したがって:

    strcpy(path, START_PATH);

が指すメモリの先に1つ書き込むことにより、未定義の動作を呼び出しますpath

于 2009-10-15T18:21:02.877 に答える
1
void TrimVal(char* modify, char* string, char* newstr)

関数内でmodifystring、またはの値を変更しても、呼び出し元の関数の変数には影響しません。newstrTrimVal()

関数内の、、またはの内容を変更すると、呼び出し元の関数の変数に反映されます。modifystringnewstrTrimVal()

そう

void TrimVal(char* modify, char* string, char* newstr)
{
    newstr[0] = '\0'; /* will be reflected in the calling function */
    modify = "a new string"; /* won't be reflected */
}

コードを少しクリアすることで、あなたの関数はあなたが望むことを行うことができると思います。

ああ...そして、path変数にメモリリークがあります。変数にスペースを割り当て、その後すぐにpath変数に別の値を割り当てることで、そのスペースのアドレスを失います。

于 2009-10-15T15:30:22.687 に答える
0

char* 変数が関数内で変更されることが予想され、参照によって渡したい場合は、それを char* として渡す必要がありますポインターを参照渡ししていることを思い出してください。そのため、追加の間接レイヤーが必要です (charを渡すと、何かを参照渡しします - 1 文字です!)。

于 2009-10-15T15:26:00.810 に答える
0

C には実際には参照渡しはありません。ここで行っているのは、ポインターを値で渡すことです。C の文字列は、 charへのポインターによって表されます。したがって、関数TrimValでは、文字列の内容 (つまり、ポイント先のデータ) を変更できますが、ポインター自体は変更できません。

strncatは最初のパラメーターの内容を変更し、同じ値を返します。

TrimVal内のpathの値を変更したい場合は、次のようにポインターをポインターに渡す必要があります。

...

TrimVal(path, "*.*", newstr);

...

void TrimVal(char** modify, char* string, char* newstr)

{ 
  newstr[0] = '\0';
  *modify = strncat(newstr, *modify, (strlen(*modify) - strlen(string)));
  return;
} 
于 2009-10-15T15:27:59.140 に答える
0

malloc 呼び出しの戻り値の型をキャストするスタイルについてのコメントが 1 つだけあります。これをキャストすると、エラーが隠される可能性があります。

これは、はるかに優れたスタイルになります。

stdlib.h をインクルードし、タイプに依存しないように malloc を呼び出してみてください。

char *ptr_char = NULL;

ptr_char = malloc(sizeof(*ptr_char));

お役に立てれば、

于 2009-10-16T04:59:37.020 に答える
0

最初の 2 つのステートメントに問題があります。path をポインター char として宣言し、このアドレスホルダーに格納されるメモリを割り当てています。次のステートメントでは、path の値を変更して、char 配列 START_PATH の先頭を指すようにします。割り当てたメモリは失われます。

また、strncat は連結のために malloc を呼び出しません。連結を保持するのに十分な大きさのバッファーを渡すことが想定されており、これは潜在的なセキュリティ リスク (バッファー オーバーラン) です。

于 2009-10-15T15:44:08.510 に答える