0

所定の位置にないcstringを逆にする関数を書いていますが、逆のcstringを返します。戻り値の型は正確には何ですか?

#include <stdio.h>
#include <string.h>

const char* reverStr(const char *str)
{
    char revStr[strlen(str)];
    int i;
    for(i = strlen(str)-1; i >= 0; i--)
        revStr[strlen(str)-1-i] = str[i];
    printf("returned value should be %s\n", revStr);
    return revStr;
}

int main()
{
    char aStr[] = "hello";
    char aStr2[] = "goodbye";
    printf("%s %s", aStr, aStr2);
    char* tmp = reverStr(aStr);//tmp now has garbage
    printf("\n%s", tmp);
    printf(" %s", aStr);
    return 0;
}

警告: 関数はローカル変数のアドレスを返します [デフォルトで有効]| 警告: 初期化により、ポインター ターゲット型から 'const' 修飾子が破棄されます [デフォルトで有効] |

に変更しようとしchar* tmpましchar tmp[]たが、コンパイルできませんでした。いつ配列を使用する必要があるのか​​ 、いつポインタを使用する必要があるのか​​ 混乱します。

4

3 に答える 3

1

revStrは配列であり、reverStr関数が終了すると存在しなくなります。詳細については、以下をお読みください:

この配列を作成すると、メモリはどこに割り当てられますか? (ハ)

const char* reverStr(const char *str)
{
    char revStr[strlen(str)];

    return revStr;  /* Problem - revStr is a local variable trying to access this address from another function will be erroneous*/
}


const char* reverStr(const char *str)
{
    const char * revStr = str;

    return revStr;  //ok
}

変更可能な左辺値に配列型を含めることはできません。左辺値は、代入の左側に置くことができる式です。同じ型の変数をたくさん宣言したい場合は配列を使用します。そのレイアウトはある意味で連続しているため、簡単にインデックスを付けることができます。

変数が指すアドレスの値を変更し続けたい場合は、ポインターを使用します。

あなたはこれを行うことができます:

char * p = "test";
p = "new";

しかし、これを行うことはできません:

    char p[] = "test";
    char *p1 ="test1";
    p = p1; //error

それらの (配列とポインター) 型は同じではなく、配列pは変更不可能な左辺値であるためです。

これが固定コードです。修正を少なくしようとしました。

于 2013-10-01T04:52:18.533 に答える
1

char revStr[strlen(str)];ローカル変数(配列)を割り当て、関数の範囲外になるとreverStr、そのメモリが解放されます。これにより、ポインターをさらに使用するとUB(ほとんどの場合segfault)になります。

正しい方法は、ヒープに文字列を割り当て、そのポインターを次のように返すことです

char* x = (char*)malloc(strlen(str));
...
return x;

これには、ユーザーがメモリを解放する責任があります。または、結果文字列の関数に別のパラメーターを渡すこともできます。

于 2013-10-01T05:00:17.980 に答える