一个程序的3个基本段:text段、data段、bss段。
特点是:可读写的,在程序执行之前BSS段会自动清0。
所以,未初始的全局变量在程序执行之前已经成0了。
注意和数据段的区别,BSS存放的是未初始化的全局变量和静态变量,数据段存放的是初始化后的全局变量和静态变量。
UNIX下可使用size命令查看可执行文件的段大小信息。如size a.out。
也就是通常所说的静态存储区,赋了初值的全局变量和赋初值的静态变量存放在这个区域,常量也存在这个区域。数据段,代码段在程序运行之前就已经确定了的。
这部分区域的大小在程序运行前就已经确定,并且内存区域通常属于只读, 某些架构也允许代码段为可写,即允许自修改程序。
在代码段中,也有可能包含一些只读的常数变量,例如字符串常量等。
text段在编译时确定,内存中被映射为只读,但date段与bss段是可写的。
堆栈是由编译器自动分配释放,存放函数的参数和局部变量的值(auto类型),操作方式类似于数据结构中的栈。栈的申请是由系统自动分配,如在函数内部申请一个局部变量int h,同时判断所申请空间是否小于栈的剩余空间,如果小于则为其开辟空间,为程序提供内存,否则将报异常提示栈溢出。
堆一般由程序员分配释放,若程序员不释放,程序结束可能由OS回收。
它与数据结构中的堆是两回事,分配方式类似于链表,申请则是程序员自己操作使用malloc或new。
申请过程比较复杂,当系统收到程序的申请时,会遍历记录空闲内存地址的链表,以求寻找第一个空间大于所申请空间的堆节点,然后将该节点从空闲节点链表中删除,并将该节点的空间分配给程序,有些情况下,新申请的内存块的首地址记录本次分配的内存块的大小,这样在free()时能正确的释放内存空间。
全局变量与静态变量的存储是放在一块的,初始化的全局变量与静态变量存放在一块区域,未初始化的全局变量与未初始化的静态变量存放在相邻的另一块区域。
常量字符串就是放在该部分,只读存储区,程序结束后由系统释放
存放程序的二进制代码区。
两者之间区别是:代码段,数据段,堆栈段是cpu级别的概念,五大分区属于语言级别的概念,两者是不同的概念。
左边是UNIX系统的执行文件,右边是进程对应的逻辑地址空间的划分情况。
static变量主要区分静态全局变量和全局变量、局部变量和静态局部变量之间的区别。
全局变量 | 静态全局变量 | |
---|---|---|
生存周期 | 程序运行到程序结束 | 程序运行开始到程序结束 |
作用域 | 所有的代码 | 只有当前文件可以访问 |
代码段中位置 | 全局数据区 | 全局数据区 |
以下是b.c 和 a.c源代码:
编译:
gcc a.c b.c
执行结果:
由编译结果可知,文件a.c可以访问到b.c文件中的静态全局变量b。
由编译结果可知,文件a.c无法访问到b.c文件中的静态全局变量b,所以编译报错。
局部变量 | 静态局部变量 | |
---|---|---|
生存周期 | 函数调用到函数返回 | 程序运行开始到程序结束 |
作用域 | 函数内部 | 函数内部 |
代码段中位置 | 栈 | 全局数据区 |
静态局部变量存放在数据段.data中,局部变量在栈中;静态局部变量和局部变量都只能在函数体内部才可以访问。
函数每次访问的静态局部变量,该变量的值为最后一次访问修改后的值。
例如:
1 #include
2
3
4 void func()
5 {
6 int aa = 11;
7
8 printf("aa= %d \n",aa++);
9
10 }
11
12 int main(int argc, char **argv)
13 {
14
15 func();
16 func();
17
18 return 0;
19 }
对于普通的局部变量,每次调用的时候,都会在栈里初始化1次,
1 #include
2
3
4 void func()
5 {
6 static int aa = 11;
7
8 printf("aa= %d \n",aa++);
9
10 }
11
12 int main(int argc, char **argv)
13 {
14
15 func();
16 func();
17
18 return 0;
19 }
函数中静态变量aa 只初始化一次,每次访问的值应该是上一次调用到该函数时最后处理的结果,
在函数的返回类型前加上关键字static,函数就被定义成为静态函数。
函数的定义和声明默认情况下是extern的,但静态函数只是在声明他的文件当中可见,不能被其他文件所用。
static函数(也叫内部函数)只能被本文件中的函数调用,而不能被同一程序其它文件中的函数调用。
区别于一般的非静态函数(外部函数) static在c里面可以用来修饰变量,也可以用来修饰函数。
先看用来修饰变量的时候。变量在c里面可分为存在全局数据区、栈和堆里。
其实我们平时所说的堆栈是栈而不包含堆,不要弄混。
a.c
1 #include
2
3 void func();
4
5 int main(int argc, char **argv)
6 {
7
8 func();
9
10 return 0;
11 }
b.c
1 #include
2
3 int b = 10;
4
5
6 static void func()
7 {
8 printf("in func b =%d\n",b);
9 }
由编译结果可知,a文件访问不到b文件中的静态函数func。
END
→点关注,不迷路←