2014-05-18 176 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的一个替代方案,该数据会自动释放时该函数返回并重置堆栈。

这是一个漫长的回答你的问题。是的,当声明一个字符时,必须有一个分配。但是,这种分配是在幕后完成的,没有您的努力。

相关问题