2011-08-16 71 views
6

這是一個基於答案由提問一個問題:字符數組VS字符*

const char myVar* vs. const char myVar[]

const char* x = "Hello World!"; 
const char x[] = "Hello World!"; 

我現在理解上的差異,但我的新問題是:

(1)什麼發生在第一行的「Hello World」字符串,如果我重新分配x?沒有什麼會指出這一點 - 當範圍結束後它會被銷燬嗎?

(2)除了常量外,這兩個示例中的值如何在編譯器中不同地存儲在內存中?

回答

9

在您的代碼中放置"Hello World!"會導致編譯器將該字符串包含在編譯的可執行文件中。在執行程序之前,在調用main之前在內存中創建字符串,我相信甚至在程序集調用__start(這是靜態初始化程序開始運行時)之前。 char * x的內容未使用newmalloc分配,或者在main的堆棧幀中分配,因此不能分配。

但是,在函數或方法中聲明的char x[20] = "Hello World"在堆棧中分配,而在範圍內,實際上在內存中將有兩個"Hello World"副本 - 一個預加載可執行文件,一個在堆棧中 - 分配緩衝區。

+0

const char x []應該將數據複製到堆棧。 –

-1
  1. 形式上在兩種情況下,"Hello World!"字符串在靜態存儲器作爲char的連續序列分配的,所以不存在動態分配的內存以回收或任何類的實例來破壞;
  2. 這兩個x將被分配在靜態存儲器或堆棧中,具體取決於它們的定義。但是,指針將被初始化以指向相應的"Hello World!"字符串,而數組將通過將字符串直接複製到其中而被初始化。

理論上,編譯器可以在沒有辦法訪問它們時自由地回收這兩個字符串文本的內存;在實踐中,第一個不太可能被回收,因爲通常靜態內存仍然被分配給程序直到其終止;另一方面,如果數組在堆棧上分配,第二個數據甚至可能根本就不被分配,因爲編譯器可能使用其他方法來確保數組已正確初始化,並且數組內存將在其退出時被回收範圍。

+0

除此之外,用指針做sizeof(x)將導致4(或64位代碼中的8),而帶數組的sizeof(x)將導致數組包含的字節數。 – Matthew

+2

-1:它們不以相同的方式分配。第一個例子是一個指向靜態內存的指針。第二個例子是一個非靜態數組,其內容用'「Hello world!」'初始化。 –

+2

我認爲const char x []背後的想法是數組在堆棧上,而不僅僅是一個指針,並且「Hello World!」被複制到它。這可能會被優化,但這個想法與簡單的指針完全不同。 –

4

編譯器將第一個存儲在名爲RODATA(只讀數據)的內存部分中。只要程序仍在運行,內存仍然保持其初始值。

第二個存儲就像任何其他數組 - 在堆棧上。就像任何其他局部變量一樣,一旦範圍結束,它就可能被覆蓋。

+0

'只要程序仍在運行,內存仍然保持其初始值。'也就是說,字符串的範圍是程序範圍,而不是函數的範圍。 –