一、代码段、数据段、bss段
- 编译器在编译程序的时候,将程序中的所有元素分成了一些组成部分,各部分构成一个段,所以说段是可执行程序的组成部分。
- 代码段:是程序中可执行部分,直观理解代码段就是函数堆叠形成的。
- 数据段(数据区,静态数据区,静态区):程序中的全局变量,各种全局变量(注意:全局变量才算是程序的数据,局部变量不算程序的数据,只能算函数数据)。
- bss算(ZI(zero initial)段):bss段的特点是被初始化为0,bss段本质也属于数据段,bss段就是被初始化为0的数据段。
总结:数据段和bss段二者本来没有本质区别,都是用来存放c中的全局变量,区别在于把显式初始化为非0的全局变量放在data段,而把显式初始化为0或者并未初始化的全局变量(为初始化的默认为0)放在bss段。
二、有些特殊的数据会被放在代码段
- c语言中使用char *p=“linux”定义字符串时,这个字符串实际被分配在代码段。这个字符串实际上是一个常量字符串而不是变量字符串。
- const型常量:在c语言中const关键字来定义常量。const的实现方法:一是编译器将const修饰的变量放在代码段实现不可修改(单片机);第二种是由编译器来检查,以确保const型常量不被修改,但const常量还是放在数据区(gcc)。
#include <stdio.h>
int main(void)
{
char *p="linux";
//const char *p="linux"; 正确的写法
*(p+0)=‘f’;
printf("p=%s.\n",p); //段错误
return 0;
}
三、显式初始化为非0的全局变量和静态局部变量放在数据段
- 放在数据段的变量有两种:一、显式初始化为非0的全局变量;第二种是静态局部变量,也就是ststic修饰的局部变量。(普通局部变量分配在栈上,而静态局部变量分布在数据段。)
#include <stdio.h>
int a=5;
int b;
int c=0;
int array[1000];
int main(void)
{
return 0;
}
四、未初始化或显式初始化为0的全局变量放在bss段
- bss段和数据段并没有本质区别,几乎可以不用明确区分这两种。
总结:c语言中所有变量和常量所使用的内存无非以上三种情况。
- 三种获取内存的方法都可以给程序提供可用 内存,都可以用来定义变量给程序用。
- 不同点:栈内存对应c中的普通局部变量(别的变量想用用不了,而且栈是自动的,由编译器和运行环境共同提供,程序员无法手工控制);堆内存完全独立于我们程序存在和管理,程序需要内存时可以收购申请malloc,使用完必须尽快free释放;数据段对应程序来说对应了c中的全局变量和静态局部变量。
- 如果 需要一段内存存储数据,究竟应该把这个数据存储在哪?不同的存储方式有不同的特点.
总结:函数内部临时使用,出了函数不会用到,就定义局部变量。堆内存和数据段几乎拥有完全相同的属性,大部分时候是可以完全替换。但是生命周期不一样。堆内存的生命周期是从malloc开始到free结束,而全局变量是从整个程序一开始执行就开始,直到整个程序结束才消灭,伴随整个程序运行的一生。如果这个变量只是在程序的一个阶段有用,用完就不用,就适合用堆内存;如果变量本身和这个程序是一生相伴的那就适合用全局变量。买不能租,堆内存的使用比全局变量的使用广泛。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char str[]="linux"; //定义全局变量,放在数据段
int main(void)
{
char *p=(char *)malloc(10);
if(NULL==p)
{
printf("malloc error.\n");
return -1;
}
memst(p,0,10);
strcpy(p,"linux"); //放在malloc申请的堆内存中
char a[]="linux"; //定义局部变量,放在栈上
return 0;
}