探究C语言不同数据类型在内存中的存储很有意思,也是学习c语言时的难点。1的内容推进2的理解,含各变量的小特性哦。
1.程序存储区域
程序(可执行文件)进行存储时分为三个区域:代码段,数据段,bss段。
代码段:存放CPU执行的机器指令。
数据段:存放已初始化的全局变量、静态变量(全局和局部)、常量数据。
BBS区:存放的是未初始化的全局变量和静态变量。
在程序运行时,系统会为其再增加两个段:堆和栈。
堆:手动进行申请(malloc)的内存块,需要手动释放(free)所申请的内存空间,malloc函数使用不当易产生内存泄露。
栈:由编译器自动的分配和释放,存放程序运行过程中产生的临时信息和数据(如函数返回值,参数值,局部变量等)。
见图;
2.变量存储类别,作用域,生存期
c语言中的存储类型有auto, register,static, extern这四种,存储类型说明了该变量要在进程的哪一个段中分配内存空间,可以为变量分配内存存储空间的有数据区、BBS区、栈区、堆区。
(1)局部auto(自动)变量
定义局部自动变量的一般形式为:
[auto] 数据类型标识符(如int) 变量名称[=初始值表达式], ...;
auto可省略,auto被省略,系统默认其为auto变量。
局部自动变量
<1>存储区:栈
<2>分配内存时间: 当函数执行到此位置时(如调用此函数时),当函数运行完毕时,自动变量的内存单元被自动释放。
<3>作用域:在被定义的的局部范围内有效。
<4>生存期:作用域内。
<5>未被赋值时值不定。
例_auto:
<span style="font-size:14px;">#include <stdio.h>
int main(void)
{
//在main函数内,i, j都属局部变量
//i, j等效,其i值不定
auto int i;
int j;
j = 1;
printf("%d\t%d\n", i, j);
return 0;
}</span>
运行结果:134513691 1
(2)register变量
<1>存储区:栈
<2>分配内存时间: 当执行到此位置时(如调用包含此变量的函数时),运行到局部变量被定义的语句时,当此函数运行完毕时,自动变量的内存单元被自动释放。
<3>作用域:在被定义的的局部范围内有效。
<4>生存期:作用域内。
<5>只有局部变量和形参可以作为register变量,全局变量不行。
register称为寄存器型,使用register关键词说明的变量主要目的是想将所说明的变量放入寄存器存储空间中,我们知道寄存器数量有限,且位于CPU的内部,这样可以加快程序的运行速度。但正因为寄存器的资源相对较少,所以编译器会判断程序所指定的需要放在寄存器中的内容有没有必要放入寄存器中去,也就是说,编译器来决定是否将指定内容放入到寄存器中,如果没有没有必要放入寄存器中,就使用auto类型作处理。还因为register变量被存储到寄存器中,所以不可以对register变量实施&(取址)操作。综上所述,register是一个建议性关键字,在实际编程中很少用到。
(3)static 变量
定义静态变量的形式:
static 数据类型 变量名称 [=初始化值],...;
<1>存储区:由<5>存储在数据段中。
<2>分配内存时间: 在应用程序初始化时。
<3>作用域:在被定义的的局部范围内有效。
<4>生存期:应用程序的生存期。
<5>未经初始化的静态变量会被程序自动初始化为0,static变量具有继承性。
例_static1:
#include <stdio.h>
int main(void)
{
static int i;
int j;
printf("%d\t%d\n", i, j);
return 0;
}
运行结果:0 -1217204236
结论:未经初始化的静态变量会被程序自动初始化为0,未经初始化的非静态变量值不定。
例_static2:
#include <stdio.h>
//验证static局部变量具继承性的子函数
void static_auto_com()
{
static int i = 0;
int j = 0;
i++;
j++;
printf("The %d time:i value:%d\tj value: %d\n", i, i, j);
}
int main(void)
{
int i;
for(i = 0; i < 3; i++){
static_auto_com();
}
return 0;
}
运行结果:
The 1 time:i value:1 j value: 1
The 2 time:i value:2 j value: 1
The 3 time:i value:3 j value: 1
结论:static静态局部变量具继承性,非静态局部变量不具继承性。
(4)extern
extern不是用来定义变量,而是用来声明在本项目(一个项目可能含有多个文件)其它文件或者本文件中定义的全局变量。这样子申明来的全局变量不会被重复分配内存空间。
<1>存储区:经初始化的全局变量被存储在数据段内,未被初始化的全局变量存储在BBS段。
<2>分配内存时间: 在程序被编译时。
<3>作用域:整个项目。
<4>生存期:应用程序生存期。
<5>全局便量为被初始化是初始值也为0.extern作为申明命令,与定义的区别:对于一个全局变量来说
定义时 次数:只能被定义一次 ;位置:全局变量只能定义在所有函数(包括main)之外 ; 可被分配以且可被初始化
声明时 次数:可多次; 位置:函数内或外 不可被分配且不可被初始化
例_extern:
#include <stdio.h>
int main()
{
//在main函数内申明在后面定义的全局变量a_var
extern a_var;
printf("a_var value is: %d\n", a_var);
return 0;
}
int a_var = 9;
运行结果:
a_var value is: 9
参考博客:http://www.embedu.org/Column/Column328.htm
http://blog.csdn.net/hackerain/article/details/7953261
3.总结:
以上的知识我们只在意对我们编程时有用的点,在编程时会用到的就是重点。在编程时暂不用的我们可在以后深究。看本文中的图形就可将本文中心掌握。
还有一种内存分配为手动分配(malloc),跟堆相关。这个得单独聊。
此次笔记记录完毕。