2014-05-18 37 views
1

原始數據類型,如char,bool和int有一些內存。假設char有1個字節的內存。當我們在代碼中使用char變量時,變量必須要求1個字節的內存。爲什麼我們不在這種情況下分配內存。而且我們從來沒有爲它分配內存,它如何使用內存,在這種情況下,CPU是否爲它分配內存。我還在某處讀取了原始數據類型放在堆棧上並在工作完成時刪除。什麼樣的堆棧?在這種情況下堆棧如何進入畫面?爲什麼沒有分配原始數據類型的內存?

+1

堆棧和堆是不同類型的內存。你的問題在這裏得到了解答:http://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap – jsd

回答

5

當我們創建一個NSString *變量時,我們也沒有爲此分配內存。

我們只在調用alloc時分配內存,可以直接由我們調用,也可以在我們調用的方法內調用。

一種NSString對象存在於我們已經分配在存儲器堆,但NSString *變量(這是一個指向NSString對象)存在於內存中,我們不分配在棧上。

例如,假設這兩個變量:

NSString *stringOne; 
NSString *stringTwo; 

到目前爲止,無論是已經在堆中分配的任何記憶,他們雖然存在於內存中的完全相同的方式charBOOL,或者int存在於內存中。

NSString *stringOne = [[NSString alloc] initWithString:@"Hello world"]; 
NSString *stringTwo = stringOne; 

現在發生了什麼事?我們在堆上爲一個NSString對象分配了一些內存。然後我們初始化這個內存來表示字符串「Hello world」,然後返回一個指向這個對象的指針並將它分配給stringOne

接下來,我們簡單地將該指針複製到我們用於stringTwo的堆棧內存中。我們沒有在堆上分配任何額外的內存。我們只是將兩個字符串變量指向堆中相同的已分配內存。

question and answer jsd linked in the comments對堆棧和堆內存有更多的解釋,它將回答你的一些問題。

還值得注意的是,許多其他編程語言(如C++)允許在堆棧上創建對象,在這種情況下,我們不會像堆對象那樣分配它們。它們確實存在於內存中,與原始數據類型更類似。

+4

正確...相關興趣的一個實現細節(但決不是反正無效); '[[NSString alloc] initWithString:@「Hello world」]'實際上不會在堆上創建一個字符串。它只會返回編譯器在mach-o文件中放置的__NSCFConstantString(或任何它所調用的)。這只是一個有趣的細節,它不會改變任何關於你所說的字符串的消費;它應該像對待任何其他對象一樣對待。 – bbum

+0

我想這個例子對於可變對象來說可能更好,因爲它們的大小需要能夠改變,所以更重要的是它們在堆上。 – nhgrif

5

在過度簡化的風險下,數據有三類內存:1)靜態,2)堆棧3)堆。

它們以不同的方式分配。

,如果你有

static char something ; 
在函數定義

char something ; 

的功能之外,該數據由鏈接器使用來自編譯器的指令所限定的以及由程序加載器分配。

幾乎每個存在的處理器都使用堆棧來支持嵌套數據(例如函數調用)。堆棧是每個進程(和每個處理器模式)都存在的一塊內存。有一個稱爲堆棧指針的硬件寄存器,用於標識堆棧的當前位置。通常SP從堆棧的高端開始向下工作。要在堆棧中分配內存,程序會從堆棧指針中減去所需的字節數。爲了釋放,它添加到堆棧指針。分配和釋放總是在同一端進行。

在堆棧上有兩個操作。 PUSH意味着把東西放在堆棧上。 POP刪除它。大多數處理器有指令push和pop

如果你有

char something 

一個函數中定義的,內存由程序分配所指示的編譯器做這樣的事情,調整堆棧指針(我在進入功能留出現在幀指針)

SUB BYTESNEEDED, SP 

,並通過做

ADD BYTESNEEDED, SP 
釋放

離開函數之前。在函數執行過程中,局部變量位於堆棧指針的偏移處。

這通常通過使用第二個寄存器來完成,通常稱爲幀指針。函數通常不會像這樣在開始

PUSH FP  ; Save the old Frame Point 
MOV SP FP ; Save the stack pointer 
SUB BYTESNEEDED, SP 

末的功能確實像

MOV FP,SP;釋放由功能 POP FP分配的所有堆棧;恢復舊的堆棧指針

使用兩個寄存器的原因是可以從堆棧動態分配數據。

有一個共同的功能(儘管相信這不是一個標準的C函數)稱爲ALLOCA被從棧

void dosomething (int amount) 
{ 
    char *data = alloca (amount) ; 
} 

隨着ALLOCA分配給malloc的一個替代方案,該數據會自動釋放時該函數返回並重置堆棧。

這是一個漫長的回答你的問題。是的,當聲明一個字符時,必須有一個分配。但是,這種分配是在幕後完成的,沒有您的努力。

相關問題