5

ここで何が欠けていますか? それは私を夢中にさせています!

const char*を返す関数があります

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

今、コードの別の部分で私はこれをやっています:

.....
.....
char str[50];       
sprintf(str, "%s", Notation());
.....
.....

ただし、strは変更されません。

代わりにこれを行う場合:

.....
.....
char str[50];
str[0]=0;
strcat(str, Notation());
.....
.....

strが正しく設定されています。

なぜsprintfが期待どおりに動作しないのか疑問に思っています...

4

3 に答える 3

9

スタックに割り当てられた配列を返そうとしていますが、その動作は未定義です。

const char* Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s;
}

関数から戻った後は、ここsには表示されませんNotation()。スレッドセーフに関心がない場合は、s静的にすることができます。

const char* Notation() const
{
    static char s[10];
    ....
于 2012-05-27T05:21:24.843 に答える
5

どちらの場合も、Notation()戻ると破棄されるローカル配列を返すため、未定義の動作を呼び出します。ある場合にそれが機能するのは不運であり、それが正しいと感じさせます。

解決策は次のように使用することstd::stringです:

std::string Notation() const
{
    char s[10];
    int x=5;
    sprintf(s, "%d", x);
    return s; //it is okay now, s gets converted into std::string
}

または、C++ストリームを次のように使用します。

std::string Notation() const
{
    int x=5;
    std::ostringstream oss;
    oss << x;
    return oss.str(); 
}

その後:

char str[50];       
sprintf(str, "%s", Notation().c_str());

std::ostringstream(および)の利点(および美しさ)はstd::string、出力のサイズを事前に知る必要がないことです。つまり10、配列宣言などのマジックナンバーを使用する必要がありませんchar s[10]。その意味で、これらのクラスは安全です。

于 2012-05-27T05:22:11.033 に答える
1

char s[10]inNotationはスタックに配置されるため、関数の終了後に破棄されNotationます。このような変数は自動と呼ばれます。次を使用して文字列をヒープに保存する必要がありますnew

char *s = new char[10];

ただし、このメモリを手動で解放する必要があります。

char str[50];
const char *nt = Notation();
sprintf(str, "%s", nt);
printf("%s", str);
delete[] nt;

実際にC++を使用する場合は、Nawazが提案するstringような組み込みクラスを使用してください。どういうわけか生のポインタに制限している場合は、バッファを外部に割り当て、inや。のようにdestanationパラメータとして渡します。Notationsprintfstrcat

于 2012-05-27T05:24:19.163 に答える