一直对堆栈的使用以及全局变量、静态全局变量、局部变量、静态局部变量、初始化的全局变量、未初始化的全局变量、初始化的局部变量、未初始化的局部变量理解的不是很清楚,今天抽个时间来总结以下这方面的知识:
1.首先心中要有一个内存分布图,最上面肯定是命令行和环境参数、往下依次是栈、堆、bss段、数据段、代码段:
- 栈是从上往下读的,所以栈放在最上面,栈里面一般存放的是局部变量,但是如果是static的静态局部变量那么其存储在全局初始化区中也就是数据段中,不管是初始化的局部变量还是未初始化的局部变量
- 堆中存放的是程序员可操控的内存,一般用malloc()申请,用free释放().
- bss段用来存放未初始化的全局变量和静态变量,(全局变量未初始化时默认为0的一段区域)
- 数据段用来存放已经初始化的全局变量和静态变量
- 代码段用来存放程序中的代码和常量
2.栈:通常指用来存放程序中用户临时创建的局部变量、函数形参、数组(局部变量未初始化则默认为垃圾值),不包括static声明的变量,static意味着在数据段中存放变量。栈可以看成时一个寄存、交换临时数据的内存区。它是由操作系统分配的,内存的申请与回收都由OS管理。。
3.用static声明局部变量:有时希望函数中的局部变量的值在函数调用后不消失而保留原值,这时就应该指定局部变量为“静态局部变量”用关键字static进行声明。
4。对静态局部变量的说明:
- 静态局部变量属于静态存储类别,在惊天存储区中分配存储单元。在程序整个运行期间都不释放。而自动变量属于动态存储类别,占动态存储类别,占动态存储空间,函数调用结束后即释放。
- 静态局部变量在编译时赋初值,即只赋值一次,而对自动变量付初值实在函数调用时进行,每调用一次函数重新给一次初值,相当于执行一次赋值语句。
- 如果在定义局部变量时不赋初值的话,则对静态局部变量来说,编译时自动赋初值0,而对自动变量来说,如果不赋初值的话是要给不确定的值。
5.register变量
- 为了提高效率,c语言允许将局部变量的值贩子啊cpu中的寄存器中,这种变量叫“寄存器变量”,用关键字register做声明
6.extern:
- 外部变量(即全局变量)是在函数的外部定义的,它的作用域为从变量定义处开始,到本程序文件的末尾。如果外部变量不在文件的开头定义,其有效的作用范围只限于定义处到文件终了。如果在定义点之前的函数想引用该外部变量,则应该在引用之前用关键字extern对该变量作“外部变量声明”。表示该变量是一个已经定义的外部变量。有了此声明,就可以从“声明”处起,合法地使用该外部变量#include
7.下面是对一个程序的举例说明:
#include//全局区
int g_n1 = 1;//全局初始化区
char g_c2 ; //全局未初始化区也就是bss段
void funtion()
{
int a = 1;
}
int main(void)
{
int nNum = 1; //栈区
char cStr2[] = "123"; //栈区
char *cStr1 = "hello"; //cStr1在栈区,hello\0在常量区
static int nNum1 = 0; //全局初始化区
char *pCStr = (char *)malloc(10); //分配10字节区域在堆区
strcpy(pCStr, "666"); //666放在常量区
printf("程序代码区的地址\n");
printf("funtion=%08X\n", funtion);
printf("文字常量区 常量的地址\n");
printf("&cStr1=%08X\n", &cStr1);
printf("&pCStr=%08X\n", &pCStr);
printf("全局区变量的地址\n");
printf("&g_n1=%08X\n", &g_n1);
printf("&g_c2=%08X\n", &g_c2);
printf("&nNum1=%08X\n", &nNum1);
printf("栈区 变量的地址\n");
printf("&nNum=%08X\n", &nNum);
printf("&cStr2=%08X\n", &cStr2);
printf("堆区 空间的地址\n");
printf("pCStr=%08X\n", pCStr);
free(pCStr);//释放
system("pause");
return 0;
}