首先,堆栈和堆是实现细节(单词"stack"和"heap"不会出现在C语言标准的任何地方).相反,该标准讨论了对象的存储持续时间(第6.2.4节).
从C2011开始,有四个存储持续时间:静态,自动,线程和已分配.
具有静态存储持续时间的对象具有在程序的生命周期内延伸的寿命1.也就是说,在加载程序时为它们留出内存,并在程序退出时释放该内存.在文件范围(在任何函数之外)或使用static关键字声明的对象具有静态存储持续时间.对于静态对象存储通常从二值图像本身内分配(对于ELF,这将包括.data,.rodata,和.bss部分); 也就是说,堆栈或堆之外的东西.
具有自动存储持续时间的对象具有从创建它们的块的条目延伸到块退出2的寿命.如果以递归方式输入块,则会创建一个新对象.在没有static关键字的块内声明的对象具有自动存储持续时间.具有自动存储持续时间的对象通常从运行时硬件堆栈分配,但并非所有体系结构都具有堆栈.
具有线程存储持续时间的对象的生命周期延长到创建它们的线程的执行时间.使用_Thread_local关键字声明的对象具有线程存储持续时间 我认为线程局部对象的分配方式与自动变量相同,但这可能是错误的; 我从未使用过C2011原生线程,所以我不能肯定地说.
与分配的存储期的对象必须是来自于它们所分配的时间延长寿命malloc,calloc或realloc直到它们被明确地将呼叫释放free.具有分配的存储持续时间的对象通常从堆中分配(尽管并非所有体系结构都具有堆本身).事情变得混乱的地方是将分配的对象与指向它的对象区分开来.给出以下代码:
int *foo( void )
{
int *bar = malloc( sizeof *bar * 10 );
// do stuff with bar
return bar;
}
void bletch( void )
{
int *blurga = foo();
// do stuff with blurga
free( blurga );
}
Run Code Online (Sandbox Code Playgroud)
我们分配了三个对象.在函数中foo,我们分配一个bar具有自动存储持续时间的指针对象(由变量引用); 它的寿命是函数的生命周期foo.在函数中bletch,我们blurga使用自动存储持续时间分配另一个指针对象(由变量引用); 它的寿命延长了函数的生命周期bletch.
第三个对象是一个足以容纳10个对象的缓冲区int.它的生命周期从malloc通话延伸foo到free通话bletch; 它的生命周期与任何函数或块的生命周期无关.
void foo()
{
printf( "entered foo\n" );
int i = 0;
while ( i < 10 )
printf( "%d\n", i++ );
}Run Code Online (Sandbox Code Playgroud)变量
的范围i从其声明的结尾延伸到块的结尾; 但是,整数对象的生命周期是i指从块条目延伸到块退出.auto对象的生命周期仅延伸到包含它的块.