比方說,我有以下規格的函數:C中的字符串參數是否動態分配?
void example(char* str)
如果我傳遞一個字符串參數,如:
example("testing");
是「測試」的值動態地分配在堆上,所以我可以在調用「example」的函數調用的作用域被銷燬(並且稍後需要釋放它)之後使用它,或者它是堆棧中的局部變量,所以我需要使一個使用malloc的新字符串,並將值存儲在那裏,如果我希望它保存在一個hashmap中?
謝謝。
比方說,我有以下規格的函數:C中的字符串參數是否動態分配?
void example(char* str)
如果我傳遞一個字符串參數,如:
example("testing");
是「測試」的值動態地分配在堆上,所以我可以在調用「example」的函數調用的作用域被銷燬(並且稍後需要釋放它)之後使用它,或者它是堆棧中的局部變量,所以我需要使一個使用malloc的新字符串,並將值存儲在那裏,如果我希望它保存在一個hashmap中?
謝謝。
當您在程序中編寫"testing"
時,它將被編譯爲字符串文字,並且會在編譯期間爲其分配空間。當你得到一個指向它的指針時,它是指向內存中的那個地方的指針。你不需要用malloc()
來分配它,你也不應該把它分配給free()
它。但是嘗試修改其內容也不是一個好主意,因爲編譯器可能會將其置於只讀區域(即它被編譯爲常量) - 例如,以下程序在我的Linux桌面上崩潰:
#include <stdio.h>
int main() {
char *a = "abc\n";
a[0]='X';
printf(a);
return(0);
}
最常見的情況是,它將作爲字符串文字存儲在可執行文件的只讀部分。實際上,您可以通過用-S
標誌編譯程序來手動驗證。
它將生成一個名爲name_of_your_app.s
的程序集可執行文件,其中可以找到字符串文字(它將位於所謂的data segment中)。
有時編譯器可以放入代碼段或取決於優化級別,它將簡單地優化它(最容易通過創建一個字符串文字來檢查,該文本不會在任何地方使用,然後使用GCC上的-O3
標誌進行編譯)。
這裏的(人爲)例如:
int main()
{
char *a = "Hai!";
return 0;
}
如果我沒有特殊標誌的字符串文字編譯它仍然存在:
$ gcc -S main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
.string "Hai!"
但是,一旦我殺青的優化級別,它不再是這種情況:
$ gcc -S -O3 main.c
main.c: In function ‘main’:
main.c:9:11: warning: unused variable ‘a’ [-Wunused-variable]
$ cat main.s | grep Hai
$
它看起來像this answer解決相同的問題。
不能保證它將以只讀方式存儲,儘管這是一個常見的實現。 –
感謝您的評論,我想偶爾可以在代碼段找到它,或者由編譯器進行優化。我會爲我的答案添加更新。 – Nobilis
或者它可以存儲在讀/寫存儲器中。嘗試修改字符串文字有未定義的行爲,所以它*可以*「工作」,具體取決於實現。 –
在C中,引號之間的字符串「such as this」被稱爲字符串文字。
字符串文字(如上面給出的內容)不會動態分配。通常,它們在編譯和/或鏈接時被分配,並且可以被分配在只讀存儲器中。 (這就是爲什麼,在C++,字符串是const char
而非char
。)
引擎蓋下,一些編譯器藏匿在一個字符串表「測試」,產生一個特殊的指針。這大致相當於這個:
char *const compiler_generated_pointer_to_testing = (char *) (compiler_generated_string_table + 12345);
...
const char compiler_generated_string_table[] = {
...
't', 'e', 's', 't', 'i', 'n', 'g', 0,
...
};
...
example(compiler_generated_pointer_to_testing);
這是它可以發揮出來的一種方式。許多其他實現是合法的。在任何情況下,實現細節可能都是重點。要記住真正的要點是:
const
,即使編譯器不要求你指針作爲const char *
宣佈他們。foo("testing")
和bar("testing")
)不保證是不同的指針,也不保證它們是相同的指針值。free()
字符串。明白了嗎?任何問題?
FWIW,在C語言中,字符串文字不是'const char'的唯一真正原因是C最初沒有以這種方式定義它們。當「const正確性」獲得蒸汽作爲編程範例時,C語言具有重要的安裝基礎,如果字符串文字追溯爲「const」,則該基礎將會中斷。 C++沒有這個負擔。 如果你真的想用你的代碼加皮帶和大括號,儘可能的聲明你的指針'const'。用他自己的話來說,John Carmack已經成了一個「常規」納粹分子:http://www.phoronix.com/scan.php?page=news_item&px=MTI3NDQ –
[是靜態內存中創建的C++中的字符串字面值?](http://stackoverflow.com/questions/349025/is-a-string-literal-in-c-created-in-static-內存) – paddy
@paddy - 儘管類似的名字,C和C++是不同的野獸。但你是正確的,肯定有這個重複。 – mouviciel
嗯,我記得在過去回答這個問題,但無法列出[我的答案](http://stackoverflow.com/questions/14468697/where-is-memory-allocated-with-a-const-char-pointer/14468729#14468729)作爲重複,因爲問題隨後被關閉並標記爲重複。相反,我列出* that * duplicate,這恰好用C++來表達。 – paddy