1、动态内存管理
内存分为5大区域:
栈:存放局部变量
堆:存放程序运行过程中,动态申请的空间
BSS:未初始化的全部变量,和静态变量
数据段:已经初始化的全局变量和静态变量 常量
代码段:程序源代码编译生成的二进制文件
1) malloc
(void *)malloc(size) //动态的向内存申请连续的size个字节
返回的是新申请的内存空间的首地址
int *p = (int *)malloc(100);
//p是在栈区 malloc(100)在堆区
malloc不会把新申请的空间初始化
memset(p,0,100); //全部初始化为0
2) calloc
calloc 可以向堆区连续申请多个少长度为指定长度的空间
int *p = (int *)calloc(5,4); //申请5个长度为4的空间
calloc可以把新申请的空间初始化0
注意:判断一个空间是否申请成功
if(p!=NULL){
//只有申请成功了,才能操作
}
3) realloc
重新改变一块内存空间的大小
p = (int *)realloc(p,size);
4) free
释放我们指定的内存空间
free(p); //p是我们新申请的内存单元
如果不释放,造成内存的泄露
2、指针和函数之间的关系
1)返回值值是指针的函数 指针函数
char * getday(){
return "星期一";
}
int * getAddr(int *a,int *b){
return *a>*b?a:b;
}
2)函数指针
指向函数的指针
格式:返回值 (*指针变量名)(函数的参数);
int sum(int a,int b){
return a+b;
}
//定义一个函数指针p1,p1只能指向返回值是int类型,并且函数参数有两个,而且整形
int (*p1)(int a,int b);
int (*p2)(int,int);
技巧:
声明的格式:int sum(int a,int b);
int (*p3)(int a,int b);
4、结构体基本概念
构造类型:由一个或者多个相同类型或者不同类型已经定义的变量用构造的方法,构造一个新的类型;
数组 结构体 共用体
结构体定义:
struct 结构体名 {
成员列表; (格式:数组类型 成名名)
};
使用构造类型的步骤:
定义构造类型 -- 定义构造类型的变量 --> 结构体变量初始化
--》使用结构体的变量
5、结构体的变量定义
1)定义结构的同时,定义变量
struct Car{
int lunzi;
}car1,car2; //定义了两个结构体变量,car1和car2都是 Car类型
2)先定义结构体,后定义变量
struct Student{
int sno;
};
struct Student stu1,stu2; //stu1和stu2都是Student类型的
3)匿名结构体定义变量
struct {
int screen_size;
}iphone5,iphone6;
6、结构体变量的初始化
初始化结构体变量应注意:初始化的值得类型和顺序要一致。
1)定义结构的同时,定义变量,然后初始化
struct Car{
int lunzi;
char pp[10];
}car1={1,"BMW"},car2={2,"BYD"}; //定义了两个结构体变量,car1和car2都是 Car类型
2)先定义结构体,后定义变量,然后初始化
struct Student{
int sno;
};
struct Student stu1={438},stu2={12}; //stu1和stu2都是Student类型的
3)匿名结构体定义变量,然后初始化
struct {
float screen_size;
}iphone5={4.7f},iphone6={5.5f};
4)指定初始化的属性
struct Car{
int lunzi;
char pp[10];
}c1={.pp="xxxx"};
struct Car c2;
//c2.pp = "BMW"; X
7、结构体变量成员的访问方法
格式:结构体的变量名.成员变量名
c1.lunzi
c1.pp
8、结构的内存存储细节
结构体内存占用?
每个元素占用之和(还要考虑对齐的问题)
对齐?
为了提高读取效率,计算机每次读取一个数的倍数(防止一个数读取两次)
对齐的模数
一个结构体中,占用的字节数最大的那个数,就是对齐的模数
计算存储的时候,按照模数存储和分配存储空间
计算长度:sizeof(struct 结构名)
从结构体的第一个成员开始,每次分配模数大小的空间,要考虑空闲的空间的再利用
9、结构体的作用域
全局的结构体:从定义的位置开始 到 文件的末尾
局部的结构体:在函数的内部或者代码块内部定义的结构体
从定义的位置开始 到 所在的代码块 “}” 结束
结构体的作用域的使用,同局部变量和全局变量使用一样
10、结构体的数组
由相同类型的结构体变量组成的有序的集合。
定义格式:
1) 定义结构体的同时定义结构体数组
struct Car{
int lunzi;
int speed;
}cars[5];
2) 使用匿名结构体定义数组
struct {
int lunzi;
int speed;
}cars[5];
3)先定义结构体在定义变量
struct Car cars[5];
初始化:
1) 定义结构体数组的同时进行初始化1
struct Car{
int lunzi;
int speed;
char name[20];
}cars[2]={{2,50},{80,300}};
2)
struct {
int lunzi;
int speed;
}cars[2]={{2,50},{80,300}};
3)
struct Car cars[2]={{2,50},{80,300}};
4)先定义数组,后初始化
cars[0].lunzi = 4;
cars[0].speed = 200;
//cars[0].name="xxxx"; 错误的
strcpy(cars[0].name,"xxxx");
const char a;
//用一个整体去初始哈哈
cars[1]=(struct Car){6,100};
11、结构体指针
定义一个指针 指向 结构体变量
格式:结构体类型 * 结构体的变量名;
struct Student stu1;
struct Studetn *pstu;
pstu = &stu1;
目的:间接访问 结构体变量中保存的成员变量值
(*pstu).name (*pstu).sno
新的访问方法
pstu->name 等价于 (*pstu).name
12、结构体与函数之间的关系
1)结构体变量的成员变量做函数参数(除了数组之外,都是值传递)
2)结构体变量作为函数的参数 (值传递)
3)结构体指针作为函数的参数 (地址传递)