why memory for primitive data types is not allocated?
char、bool和int等基元数据类型有一些内存。假设char有1个字节的内存。在代码中使用char变量时,该变量必须需要1字节的内存。在这种情况下,我们为什么不分配内存呢?因为我们从来没有为它分配内存,所以它是如何使用内存的,也就是说,在这种情况下,CPU是为它分配内存的。另外,我在某个地方读到原始数据类型被放在堆栈上,并且在为它完成工作时被删除。什么样的堆栈?在这种情况下,堆栈是如何变成图片的?
在过于简单化的风险下,数据有三类内存:1)静态内存,2)堆栈内存,3)堆内存。
它们以不同的方式分配。
如果你有
1 | static char something ; |
在函数中定义的或
1 | char something ; |
在函数外部,该数据由链接器使用编译器的指令定义,并由程序加载器分配。
几乎所有现有的处理器都使用一个堆栈来支持嵌套数据(例如,函数调用)。堆栈是存在于每个进程(以及每个处理器模式)的内存块。有一个称为堆栈指针的硬件寄存器,用于标识堆栈的当前位置。通常SP从堆栈的高端开始向下工作。为了在堆栈上分配内存,程序从堆栈指针中减去所需的字节数。要取消分配,它会添加到堆栈指针。分配和解除分配总是在同一端进行。
在堆栈上有两个操作。推意味着把一些东西放在堆栈上。Pop删除了它。大多数处理器都有推送和弹出指令
如果你有
1 | char something |
在一个函数中定义,该内存由程序按照编译器的指示分配,通过这样的操作来调整堆栈指针(现在我只剩下一个帧指针)。
1 | SUB BYTESNEEDED, SP |
在进入函数并通过执行释放后
1 | ADD BYTESNEEDED, SP |
离开功能前。在函数执行期间,局部变量与堆栈指针的偏移量。
这通常通过使用第二个寄存器来完成,通常称为帧指针。函数通常在开始时执行类似的操作
1 2 3 | PUSH FP ; Save the old Frame Point MOV SP FP ; Save the stack pointer SUB BYTESNEEDED, SP |
最后,函数的作用是
mov fp,sp;释放函数分配的所有堆栈pop fp;还原旧堆栈指针
使用两个寄存器的原因是可以从堆栈动态分配数据。
有一个名为alloca的公共函数(尽管我认为它不是标准的C函数),它是从堆栈分配malloc的替代方法
1 2 3 4 | void dosomething (int amount) { char *data = alloca (amount) ; } |
使用alloca,当函数返回并重置堆栈时,数据会自动释放。
这是对你问题的冗长回答。是的,当声明一个字符时,必须为它分配一个分配。但是,这种分配是在幕后完成的,而您不需要付出任何努力。
当我们创建一个
我们只在直接由我们调用
在我们分配的内存中的堆上存在一个
例如,给定这两个变量:
1 2 | NSString *stringOne; NSString *stringTwo; |
到目前为止,还没有在堆上分配任何内存,尽管它们确实以与内存中存在
1 2 | NSString *stringOne = [[NSString alloc] initWithString:@"Hello world"]; NSString *stringTwo = stringOne; |
现在发生了什么?我们在堆上为一个
接下来,我们简单地将指针复制到我们用于
注释中链接的问答JSD对堆栈和堆内存有更多的解释,它们将回答您的一些问题。
值得注意的是,许多其他编程语言,如C++,允许在堆栈上创建对象,在这种情况下,我们不分配它们,就像我们使用堆对象一样。它们确实存在于内存中,更类似于原始数据类型。