2012-05-27 21 views
5

私はここで何が欠けていますか?それは私のナッツを運転している!C++:sprintfでconst char *を印刷できないのはなぜですか?

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

しかしSTRは変わらない:

は、私がこれをやっているコードの別の部分で今のconstのchar *

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

を返す関数を持っています。

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

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

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

私は予想通りはsprintfが動作しない理由を疑問に思って...

+0

おそらく1つのアイデアは、関数を以下のように変更することです:void Notation(char * buffer)constそして呼び出し側提供のcharバッファで動作します。 – Wartin

+0

なぜdownvote?問題は明確で、努力を示す「働く」サンプルが与えられ、実際の問題のサンプルが与えられます。 – chris

答えて

9

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

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

sは、関数Notation()から戻ってきた後、周りのことを行っていません。スレッドの安全性に関心がなければ、sを静的にすることができます。両方の場合において

+0

私はバッファがコンパイル時に割り当てられ、アプリケーションの存続期間中そこにとどまると考えました。これが真でない場合、非グローバルconst char *を返すすべての関数が間違っていることを意味しないでしょうか? (危険な) – Wartin

+1

自動const char *を返す関数は危険です。バッファを返す方法は他にもたくさんあります。たとえば、mallocを使って静的バッファや新しく割り当てられたバッファなどです。しかし、mallocされたバッファを返すと、クリーンアップを適切に管理する必要があります。 – hawk

+0

@Wartin:文字列リテラルを考えていると思います。たとえば、次のように言った場合: 'return" foobar ";' - "foobar"という文字列がアプリケーションの存続期間中存続するので、安全です。 –

5
const char* Notation() const 
{ 
    static char s[10]; 
    .... 

Notation()が復帰に破壊されますローカル配列を返すように、それは、未定義の動作を呼び出します。あなたは不運です。それは1つのケースで働くので、と感じています。

溶液としてstd::stringを使用することである。std::ostringstream

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

利点(および美):

として
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(); 
} 

、次いで(とstd::string)は、出力iのサイズを知る必要がないということですこれは、配列宣言char s[10]10のようなマジックナンバーを使用する必要がないことを意味します。これらのクラスはその意味で安全です。

1

char s[10]Notationがスタックに置かれますので、Notation機能を終了した後に破壊されます。そのような変数はautomaticと呼ばれます。

char *s = new char[10]; 

しかし、あなたは手動でこのメモリを解放する必要があります:あなたは newを使ってヒープ内のあなたの文字列を保存する必要があり

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

をあなたが本当にその後、ビルトイン使用stringクラスNawazが提案のようにC++を使用している場合。何らかの理由で生ポインタに制限されている場合は、Notationの外側にバッファを割り当てて、またはstrcatのようにdestenderのパラメータを渡します。

+1

これで問題は解決しますが、それはひどい考えです。彼が現在のように機能を使用しようとすると、メモリリークが保証されます。 –

+0

はい、そうです。問題はC++に関するものなので、 'string'が最適です。 – Kirill

関連する問題