2012-05-27 90 views
5

我在這裏錯過了什麼?這讓我瘋狂!C++:爲什麼我不能用sprintf打印const char *?

我有代碼的另一部分返回爲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()); 
..... 
..... 

海峽保持不變。

相反,如果我這樣做:

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

STR設置正確。

我很奇怪,爲什麼預期的sprintf沒有工作...

+0

也許一個想法是將函數改爲: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爲靜態。

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

我認爲緩衝區是在編譯時分配的,並在應用程序的整個生命週期中保持不變。如果不是這樣,那麼這是不是意味着每個返回非全局const char *的函數都是錯誤的? (和危險) – Wartin

+1

任何返回自動const char *的函數都是危險的。還有很多其他的返回緩衝區的方法 - 例如static和使用malloc的新分配的緩衝區。但是,如果您返回malloc'd緩衝區,則必須正確管理清理。 – hawk

+0

@Wartin:我想你在考慮字符串文字。例如,如果你說:'返回foobar「;' - 這將是安全的,因爲字符串」foobar「持續應用程序的生命週期。 –

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)是你不必知道輸出的大小前進,這意味着您不必在數組聲明char s[10]中使用幻數,如10。這些類在這個意義上是安全的。在Notation

1

char s[10]放在棧因此它會從Notation函數退出後銷燬。這些變量被稱爲automatic。你需要使用new,以節省您的堆字符串:

char *s = new char[10]; 

但是你必須手動釋放此內存:

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

如果你真的用C++,然後使用內置string類像Nawaz建議。如果你以某種方式限制爲原始指針,則在Notation之外分配緩衝區並將其作爲destanation參數,如sprintfstrcat

+1

雖然這將解決問題,但這是一個可怕的想法。如果他試圖按照他現在的方式來使用這個功能,那將是一個有保證的內存泄漏。 –

+0

是的,就是這樣。既然問題是關於C++,那麼'string'是最好的選擇。 – Kirill

相關問題