代码区
存放函数体的二进制的代码
数据段
1.只读数据段
是程序中一般不会被改动的数据,所以一般会用const修饰,也就是常量,常量分为局部常量和全局常量,局部常量是放在栈区的,而全局常量是放在全局区的。
2.已初始化的读写数据段
已初始化数据是在程序中声明,并且具有初值的变量,这些变量需要占用存储器的空间,在程序执行时它们需要位于可读写的内存区域内,并且有初值,以供程序运行时读写。在程序中一般为已经初始化的全局变量,已经初始化的静态局部变量。
3.未初始化的数据段
又称BSS段,未初始化数据是在程序中声明,但是没有初始化的变量或者初始化为0,这些变量在程序运行之前不需要占用存储器的空间。与读写数据段类似,它也属于静态数据区。但是该段中数据没有经过初始化或者初始化为0。未初始化数据段只有在运行的初始化阶段才会产生,因此它的大小不会影响目标文件的大小。在程序中一般是没有初始化的全局变量和没有初始化的静态局部变量或者初始化为0。
栈区
由编译器自动分配释放,存放函数的参数值,局部变量等值。其操作方式类似于数据结构中的栈。在函数体内的局部变量是存在于栈区的,当函数运行完之后内部的数据就会出栈消失,所以这里注意,当需要获取栈区变量地址时不能直接返回,需要在函数内部由程序员手动开辟空间,才能正确返回。
#include <stdio.h>
#include <stdlib.h>
int *func(){
int a=100;
return &a;
}
int main(){
int *p=func();
printf("%d\n",*p);
return 0;
}
这里不但编译后会有警告,而且运行后还会出现段错误,就是因为在函数内部开辟的空间在结束之后就会消失,传递到main函数之后就是对空指针操作,所以会报错,所以我们可以用两种方法来解决,第一种是使a变量变为静态变量,因为静态变量会放在全局区,生命周期是整个程序,第二种是手动开辟空间。
第一种
#include <stdio.h>
#include <stdlib.h>
int *func(){
static int a=100;
return &a;
}
int main(){
int *p=func();
printf("%d\n",*p);
return 0;
}
第二种
#include <stdio.h>
#include <stdlib.h>
int *func(){
int a=100;
int *p=(int *)malloc(4);
p=&a;
return p;
}
int main(){
int *p=func();
printf("%d\n",*p);
return 0;
}
堆区
由程序员手动开辟的空间存放在堆区,系统不作干涉,但如果没有手动释放掉的话,在程序运行结束后就会被系统自动回收
#include <stdio.h>
#include <stdlib.h>
int *func(){
int a=100;
int *p=(int *)malloc(4);
p=&a;
return p;
}
int main(){
int *p=func();
printf("%d\n",*p);
return 0;
}
这里就是在堆区开辟了空间用来储存变量的,因为没有free掉所以在程序结束前该片空间都有效,这也就是为什么能返回正确的原因