存在过于简单化的风险,数据的内存分为三类:1) 静态,2) 堆栈 3) 堆。
它们以不同的方式分配。
如果你有
static char something ;
在函数中定义或
char something ;
在函数之外,该数据由链接器使用来自编译器的指令定义并由程序加载器分配。
几乎现有的每个处理器都使用堆栈来支持嵌套数据(例如,函数调用)。堆栈是存在于每个进程(以及每个处理器模式)的内存块。有一个称为堆栈指针的硬件寄存器,用于标识堆栈的当前位置。通常 SP 从堆栈的高端开始并向下工作。为了在堆栈上分配内存,程序从堆栈指针中减去所需的字节数。要解除分配,它会添加到堆栈指针。分配和释放总是在同一端进行。
堆栈上有两个操作。 PUSH 意味着将某些东西放在堆栈上。 POP 将其删除。大多数处理器都有 PUSH 和 POP 指令
如果你有
char something
在函数中定义,该内存由程序按照编译器的指示分配,方法是执行类似的操作来调整堆栈指针(我现在省略了帧指针)
SUB BYTESNEEDED, SP
进入函数并通过doing释放
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 ;恢复旧的堆栈指针
使用两个寄存器的原因是可以从堆栈中动态分配数据。
有一个名为 alloca 的通用函数(虽然我相信它不是标准的 C 函数),它是 malloc 的替代方法,从堆栈中分配
void dosomething (int amount)
{
char *data = alloca (amount) ;
}
使用alloca,当函数返回并重置堆栈时,数据会自动释放。
这是对您问题的冗长回答。是的,当声明一个字符时,必须对其进行分配。但是,此分配是在幕后完成的,您无需付出任何努力。