内存分区
C语言的五大分区分别是:栈区、堆区、全局/静态区、常量区、代码区,这个五个区的地址是由高到低的。
一、栈(stack)
栈,就是那些由编译器需要的时候分配,在不需要的时候自动清理的变量的存储区。里面的变量通常是局部变量、函数参数等。
- 栈区内部按内存地址由高到低方向生长,其最大大小由编译时确定,速度快,但自由性差,最大空间不大。
- 栈区是先进后出原则。
- 临时创建的局部变量、const定义的局部变量、函数参数放在这里
二、堆(heap)
就是那些由malloc分配的内存块,他们的释放编译器不去管,由我们的应用程序去控制,一般一个malloc就要对应一个free,如果程序员没有释放掉,那么在程序结束后,操作系统会自动回收。
- 堆区内部按内存地址由低到高方向生长,其大小由系统内存/虚拟内存上限决定,速度较慢,但自由性大,可用空间大。
三、全局/静态区
全局/静态存储区,全局变量和静态变量被分配到同一块内存中,在C语言中,全局变量又分初始化的和未初始化的,在C++里面没有这个区分,他们所在用一块内存区。全局区有 .bss段 和 .data段组成,可读可写。
- .bss段
- 未初始化的全局变量和静态变量以及初始化为0的全局变量和静态变量存放在.bss段。
- .bss段不占用可执行文件空间,其内容由操作系统初始化。
- .data段
- 已初始化的全局变量和静态变量存放在.data段。
- .data段占用可执行文件空间,其内容有程序初始化。
四、常量存储区
常量存储区,这一块比较特殊的存储区,他们里面存放的是常量,不允许修改。
- 字符串、数字、const修饰的全局变量等常量存放在常量区。
五、代码区
程序执行代码存放在代码区,其值不能修改(若修改则会出现错误)。
- 字符串常量和define定义的常量也有可能存放在代码区。
结构体
结构体定义和初始化
struct student
{
int num;
char name[20];
int age;
};
struct student s = {10,"hhh",20}; //初始化
printf("%d %s %d",s.num,s.name,s.age);
用typedef定义结构体,typedef相当于给变量类型起别名
例:int a = 10;
typedef int uint32;
那么uint32 a = 10;
uint32就是int的别名。
struct student
{
int num;
char name[20];
int age;
}st;
st s = {10,"hhh",20}; //初始化
这里的st就是struct student的类型
*(p).num <==> p->num
//结构体还是上述结构体
struct student s[20] = {{1,"saf"},{2}};
struct student* p = s;
printf("%d %s %d",(*p).num,(*p).name,(*p).age);
printf("%d %s %d",p->num,p->name,p->age);
字节对齐
struct student
{
char name;
int age;
}st;
printf("%d", sizeof(st));//8
struct student
{
char name;
short n;
int age;
}st;
printf("%d", sizeof(st));//8
struct student
{
char name;
int age;
char m;
}st;
printf("%d", sizeof(st));//12
字节对齐在结构体中是按最长字节进行对齐的,以第三个结构体为例,最长字节是int 4个字节,所以按4个字节对齐。
char name会申请一个4字节的空间,但是还有三个字节的空间空着,但放不下int age,所以就需要在申请一个4字节的空间,最后一个char m同理,所以一个需要12个字节。
#pargma pack(4)//强行按4个字节对齐
#pargma pack(1)
struct student
{
char name;
int age;
char m;
}st;
printf("%d", sizeof(st));//6
联合
联合和结构体类似,但作用和大小不同,联合的大小是几个类型中最大的那个值。
union student
{
int n;
int age;
};
union student un;
printf("%d", sizeof(un));//4
union student
{
int n;
int age;
char m;
};
union student un;
un.n= 100;
printf("%d", sizeof(un));//4
printf("%d", un.age);//100
printf("%d", un.m);//100
printf("%c", un.m);//d
联合的作用:一般来说,不同的变量存在不同的内存,但联合中的这三个变量就存在同一段内存,只是在固定的某时刻,这个内存中只有这三个元素的其中一个元素存在,说到底是省了内存空间
字节序
用联合判断是网络序还是主机序
int checksystem()
{
union un
{
char i;
int j;
}u;
u.j = 1;
return u.i == 1;
}
解释:以上图12-15地址为例
- 首先int和char共享一块空间
- char是低位,是在地址为12的位置
- 如果是大端存储,1这个值就应该放在地址为12的位置,也就是说如果return 1,就是大端存储。
- 如果是小端存储,1这个值就应该放在地址为15的位置也就是说如果return 0,就是小端存储。