内存分区、结构体、字节对齐、联合

本文详细介绍了C语言的内存分区,包括栈区、堆区、全局/静态区、常量区和代码区,以及结构体、字节对齐、联合和字节序的概念。栈区存放局部变量和函数参数,堆区由malloc/free管理,全局/静态区存储全局变量和静态变量,常量区保存常量,代码区存放程序执行代码。此外,还讨论了结构体的初始化、字节对齐的规则以及联合的使用。
摘要由CSDN通过智能技术生成

内存分区

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,就是小端存储。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晶小生

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值