回答
在LiveJournal的鏈路的參數是:(1)通過創建一個單獨的指針變量,並在安全孔引入了一個間接的unneccesary水平指針變量可能被覆蓋。假定以下兩個聲明:
char *p = "This is a test";
char s[] = "This is a test";
假定這些聲明是在文件範圍內,並因此既p
和s
具有靜態程度。
這裏顯示一切是如何制定了一個假設性的存儲器映射:是
0x00 0x01 0x02 0x03 0x00008000: 'T' 'h' 'i' 's' 0x00008004: ' ' 'i' 's' ' ' 0x00008008: 'a' ' ' 't' 'e' 0x0000800C: 's' 't' 0 ... ... p: 0x00010000: 0x00 0x00 0x80 0x00 s: 0x00010004: 'T' 'h' 'i' 's' 0x00010008: ' ' 'i' 's' ' ' 0x0001000C: 'a' ' ' 't' 'e' 0x00010010: 's' 't' 0 ...
在鏈路中提出的論點如下:
- 一個額外的變量 -
p
是一個明顯對象來自它所指向的字符串;它本身不包含字符串值,而s
確實包含字符串值; - 更多的攻擊點,該變量是可寫的 - 有可能重新分配
p
到別處點(也許包含惡意代碼段),而你不能重新分配s
。 - 額外的搬遷 - 不知道這是指什麼(對於我所做的工作,我從來沒有真正擔心機器級別的性能,所以我不熟悉所有的術語);
- 獲取字符串地址需要內存加載並訪問字符串本身需要兩次內存加載 - 如果您通過
p
讀取字符串,首先必須加載0x00010000的內容以獲取字符串地址(0x00008000 ),那麼你必須加載0x00008000的內容來獲取字符串值本身。如果你正在做一個很多,然後用字符數組和切割出一層間接可能導致noticable的性能提升。
總之,你交易,以提高速度和安全性一點記憶。當然,這是假定一個特定的操作環境,並不一定適用。
我必須堅持,因爲我對PMG的評論的回覆一樣,那是你只定義了's',那麼就不必包含目標文件中的文本字符串,所以你*不*買賣內存速度更快(和更安全的訪問),你正在節省內存*和*更快,更安全的訪問。實際上,OP提供的鏈接提倡使用較低內存使用的''樣式定義。我會用證明更新我的答案。 – 2009-11-20 15:22:14
這是一個很好的解釋,除了這個結論「權衡」的評論。 – 2009-11-20 15:23:01
在編寫動態庫的上下文中的「附加重定位」 - 加載庫時,必須根據庫的加載地址更新對靜態對象的所有引用。第一種情況有兩個靜態對象('a'和未命名的字符數組),而第二種情況只有一個。 – caf 2009-11-21 02:54:17
在(2)將字符串只存在於一個版本,你是直接通過其地址操縱它。
在(1)是在某個地方在內存中的字符串,然後你把這個地址在另一個位置在內存中,強迫自己從其他位置每次需要它時讀取的地址。實際上,它增加了一個(無用的)間接。
編輯:
正如我在下面的意見和另一個答案說,有是沒有重複(2)。
T.C:
char *p = "This is a test";
char s[] = "This is a test";
命令gcc -S t.c
產生該文件:
.globl _p
.cstring
LC0:
.ascii "This is a test\0"
.data
.align 2
_p:
.long LC0
.globl _s
_s:
.ascii "This is a test\0"
.subsections_via_symbols
ts.c:
char s[] = "This is a test";
命令gcc -S ts.c
現在生產的文件:
.globl _s
.data
_s:
.ascii "This is a test\0"
.subsections_via_symbols
不。在1)'a'是一個指針,它的內容是一個指向字符串文字的指針; 2)'了'是一個數組,其內容是構成字符串文字字符** **複製爲陣列創建 – pmg 2009-11-20 12:12:49
@pgm然而,在2內存),並因爲它是一個全球性的,我們正在談論在這裏,複製是在編譯時進行的。在「副本」之後,可以從二進制文件中省略現在沒用的字符串文字。你可能想到'char a [] =「...」;'作爲提供全局char數組的初始化的一個方便的語法。 – 2009-11-20 14:11:30
嚴格地說,不是「因爲它是全球性的」,而是「因爲它具有靜態存儲時間」。 – caf 2009-11-21 02:47:46
他們是不同的東西,而不是可更換間。
使用1)當你需要一個指針;使用2)當你需要一個數組時;使用3)當你需要一個可調整大小的陣列
3)
#define LITERAL "..."
char *a = malloc(strlen(LITERAL) + 1);
if (!a) /* no memory; */
strcpy(a, LITERAL);
- 1. Ç指定字符串指針到其他字符串指針
- 2. 靜態指針
- 3. C++的typedef靜態函數指針:未定義的符號
- 4. 指定一個字符串值指針
- 5. 字符串指針
- 6. 分配靜態內存的結構中定義的字符指針在C
- 7. 指定字符串指向字符指針
- 8. 動態分配字符指針,指針
- 9. 如何定義指向sqlite3結構的靜態指針? C++
- 10. 指向靜態的指針
- 11. 複製字符串指針,指針
- 12. 靜態數組指針vs非靜態數組指針
- 13. 靜態字符串vs非靜態字符串
- 14. Android非靜態字符串靜態字符串錯誤
- 15. C字符串和指針
- 16. 指針 - 字符串C++
- 17. 字符串指針功能
- 18. 字符串和指針
- 19. C,指針,字符串
- 20. 指針和字符串
- 21. c字符串指針
- 22. c字符串指針
- 23. 字符串指針修改
- 24. C字符串和指針
- 25. 字符串指針和strcpy
- 26. Java - 靜態定義的字符列表
- 27. 將const指針定義爲const字符串
- 28. 動態字符指針數組爲字符串
- 29. 字符指針和字符串
- 30. 字符串與字符指針
另見我的回答對您的[前一個問題] [^ 1]爲什麼最好使用數組與指針。 [^ 1]:http://stackoverflow.com/questions/1769089/defining-const-pointer-to-a-const-string/1769163#1769163 – LnxPrgr3 2009-11-20 17:30:10