2011-07-29 35 views
0

問題之前一直在問,但對於最佳方式我仍然有點不知所措。我有一個整數,並希望獲得一個char *作爲一個結構的成員使用。整型數字爲char *爲傻瓜

類似的問題,例如 herehere。 我寧可不使用stringstream或lexical_cast。據我所見,基本上離開itoa,sprintf和snprintf。

我想我的問題的一部分是,我不知道如何字符指針的工作。

  1. 如果我要求char str[12],那保留12個字符?
  2. 我認爲內存已被分配?
  3. 那麼null終止如何工作?
  4. 是否在12個字符的末尾(有空格填充?)或 (如果該數字只使用2個字符,是否會在兩個字符之後發生?
  5. 緩衝區大小是否重要,或者我應該去一些最大的 (30我認爲對於32位)?
  6. 如果我稍後在一個簡單的結構中使用指針,將自動清除內存 還是需要析構函數?
  7. 析構函數是否需要知道初始化緩衝區大小?
  8. 爲什麼沒有人打算計算從 實際數量的緩衝區長度?
  9. snprintf推薦itoa嗎?

感謝

+0

爲什麼嚴格要求?你應該閱讀這個清除指針和數組之間的混淆。 http://stackoverflow.com/questions/4810664/how-do-i-use-arrays-in-c –

+0

該char *是在第三方結構定義。我不會自己使用它們(正如你可以從問題中得出的那樣)。 – Cookie

+0

簡化你的生活:使用'std :: string'和'std :: stringstream'。另見'std :: string :: c_str()'。 –

回答

2

如果我請求一個字符str [12],保留12個字符?

是的,這預留12個字符(字節)在堆棧

我認爲內存已經被賦值了嗎?

str現在指向已經在堆棧上分配的連續內存的12個字節的開始。

那麼null終止如何工作?那是在12個字符的末尾(用空格填充嗎?),或者如果該數字只使用2個字符,是否會在兩個字符之後發生?

在這種情況下,您必須自己終止字符串(它不會自動發生此類型的聲明)。

所以,如果你想使str舉辦一些(空值終止)的字符串值,你會做以下幾點:

str[0] = 'c'; 
str[1] = 'a'; 
str[2] = 't'; 
str[3] = '\0'; 

另一種方式來獲得一個空值終止字符串是做到以下幾點:

char *str = "cat"; // this is null-terminated 

沒有自動填充空格。

如果我稍後在一個簡單的結構中使用指針,內存是否會自動清除還是需要析構函數?

如果指針指向堆棧上分配的一塊內存,那麼當堆棧彈出時內存將被恢復。否則,如果您在堆上分配內存,例如:

char *newStr = new char[12]; 
char *mallocStr = (char*) malloc(sizeof(char) * 12); 

然後,你將不得不解除分配使用deletefree存儲器(取決於哪個方法,你使用)。

析構函數是否需要知道初始化緩衝區大小?

在這種情況下,我們談論的是堆分配內存,因此答案是否定的。系統知道分配了多少內存。這就是爲什麼您只需指定deletefree而不必提供大小。

爲什麼沒有人打擾從實際的數字計算緩衝區的長度?

你可以,如果你知道你的電話號碼絕不會超過一定金額(比如,4位數字),但它通常是容易只是給出最大可能長度,因爲到最後你只能被浪費每個字符串幾個字節,除非你有一些非常嚴格的內存限制,這不是什麼大不了的。

snprintf推薦itoa嗎?

我會說是因爲snprintf被認爲是「安全的」,因爲它尊重你給它的緩衝區大小,而itoa會很樂意填寫您的緩衝區,而不檢查其大小(可能會運行超過已分配的空間和覆蓋其他內存)。

int num = 12345; 
char *str = new char[4]; 

// this is bad because str is not big enough to hold the number 
// itoa does not check buffer size and will overrun the buffer (overwriting other data) 
str = itoa(num, str); 

// snprintf takes the buffer size as one of it's arguments 
// in this case the whole number will not fit, but at least we don't overrun the buffer 
snprintf(str, 4, "%i", num); 

兩個snprintfitoa將空字符結束的字符串爲您服務。

+0

'snprintf'應該是這樣,但是有一些錯誤的實現,儘管它可以防止初始緩衝區溢出,但它不會正確地空終止。 –

+0

謝謝,那個排序 – Cookie

0

如果你真的不想使用std::stringstreamlexical_cast,你應該使用snprintf因爲它有一個緩衝區大小參數。 itoa不是ISO C函數。

Null(字符'\ 0',值爲0)可以出現在緩衝區中的任意位置,大多數使用字符串的函數在該點之後忽略緩衝區中的所有內容,所以它有點「浪費」空間。

假設您有一個像

char str[] = { 'a', 'b', 'c', '\0', 'd' }; 

的最後一個元素仍然存在,即使像printf停止功能在處理數據時遇到0:不是每個函數做到這一點,雖然。

數組(或任何其他原始數據類型)沒有構造函數或析構函數。如果你自己使用new,new[],malloc或類似的東西來分配它,你只需要擔心釋放分配的內存。

緩衝區大小當然是重要的,如果它太小,它不能容納數字的每個字符,如果它太大,就會浪費內存。 22個字符應該能夠保存每64位整數(但不是浮動/雙打!)。

最好的選擇是使用std::stringstreamstd/boost::lexical_caststd::string,它會爲您處理所有這些問題。

我建議你閱讀Martinho的鏈接,內容非常豐富。 (數組不是指針!)