这便文章是知识型🧣🧣🧣的文章,小编认为不仅要做到知识的分享还要给枯燥的知识内容🧩🧩🧩,加上一些有趣的东西🎉🎉🎉
如果您认可小编的努力,希望得到您的一个赞🙏🙏🙏
flag:键盘敲烂,月薪过万。东方不败,唯我独尊👍👍👍
是不是回到初中的感觉,或者高中,一入编程深似海,函数从此成堆来。😭😭
void * malloc(size_t size);
人物 | 简介 |
---|---|
malloc | 向内存申请一块连续可用的空间,并返回指向这块空间的指针 |
战斗力 | 开辟成功——返回一个指向开辟好的空间的地址 |
开辟失败——返回一个NULL【啥也没有,啥也不是】 | |
特点 | 返回的类型是void* ,malloc函数不知道开辟空间的类型,在具体使用的时候自己决定【就好像熊孩子自己干了坏事,自己都事情的严重型,只有发现时才能定性后果的严重】 |
当然不要忘记了熊孩子的父母——头文件
#include
#include
#include
int main(){
//动态开辟内存
int* p=(int*)malloc(10*sizeof(int));//也可以写成数字但是不推荐
if(p==NULL)
{
perror("main");
return 0;
}
for(int i=0;i,10;i++)
{
//结果为随机值
printf("%d\n",p[i]);//p[i]==*(p+i)
}
free(p);//回收空间
p=NULL;//手动设置p为NULL
}
如果开辟的空间过大会开辟失败:mian(Not enough space)
void fre(void * ptr);
人物 | 简介 |
---|---|
free | 用来释放动态开辟的内存 |
异常 | 如果ptr指向的空间不是动态开辟的,free函数的行为是未定义的 |
如果ptr是NULL指针,则函数什么都不做 |
void * calloc(size_t num,size_t size);
Allocates an array in mamory with elements initialized to 0
翻译的意思就是:会初始化内存中的数组为0
#include
#include
int main(){
int* p=(int* )calloc(10,sizeof(int));
if(p==NULL)
{
perror("main");
return 1;
}
for(int i=0;i<10;i++)
{
printf("%d",p[i]);
}
free(p);
p=NULL;
}
void* reallic(void* ptr,size_t size);
ptr——要调整的内存大小
size—— 调整之后新大小
返回值是调整之后的内存的起始位置
在调整原内存空间的基础上,还会将原来内存中的数据 移动到新的空间
int main()
{
//类似于malloc,直接在堆区开辟内存
int *p=(int* )realloc(NULL,10*sizeof(int));
}
void test()
{
int*p=(int*)malloc(INT_MAX/4);
*p=20;//如果开配失败,p是空指针,就会有问题
free(p);
}
#include
int main()
{
int *p=(int *)malloc(10*sizeof(int));
if(p==NULL)
return 1;
for(int i=0;i<20;i++)
{
p[i]=i;//i>9之后是越界的
}
free(p);
p=NULL;
return 0;
}
#include
int main() {
int arr[10]={0};//栈区
int * p=arr;
free(p);//使用free释放非动态内存开辟的空间
p=NULL;
return 0;
}
void test()
{
int* p=(int *)malloc(100);
p++;
free(p);//p不在指向动态内存的起始位置
int *p=(int *)malloc(10* sizeof(int));
if(p=NULL)
return 1;
for(int i=0:i<2;i++)
{
*p++=i;
}
free(p);
p=NULL;
return 0;
}
int main()
{
int*p=(int*)malloc(10);
free(p);
free(p);
return 0;
}
int main()
{
int*p=(int*)malloc(10);
free(p);
p=NULL;
free(p);//在第一次释放p之后,使p指向NULL;即使再次释放,free(NULL)不做任何操作
return 0;
}
void test()
{
//p是在栈区
//malloc()在堆区开辟
int *p=(int*)malloc(100);
if(p!=NULL)
{
*p=20;
}
//未释放内存
}
int main() {
test();
while(1);
}
这个我来讲一个故事:🎉🎉🎉
p警长安排malloc警员去犯罪集团中做卧底。【text函数中动态开辟内存】
只有他们两个人知道这件事,两人保持单线联系。一年后p警长不幸牺牲【text函数执行完成,释放栈区内存的内容】
警局再也找不到malloc了,但是还要给malloc薪水。【无法释放堆区内存,但程序不结束,仍然占用内存】
#include
#include
#include
void GetMemory(char* p)
{
p = (char*)malloc(100);
}
void Test(void)
{
char* str = NULL;
GetMemory(str);
strcpy(str,"hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
char* GetMemory(char* p)
{
p = (char*)malloc(100);
return p;
}
void Test()
{
char* str = NULL;
str=GetMemory(str);
strcpy(str,"hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
#define _CRT_SECURE_NO_WARNINGS
#include
#include
#include
void GetMemory(char** p)
{
*p = (char*)malloc(100);
return p;
}
void Test()
{
char* str = NULL;
GetMemory(&str);
strcpy(str,"hello world");
printf(str);
free(str);
str = NULL;
}
int main()
{
Test();
return 0;
}
char* GetMemory()
{
char p[]="Hello world";
return p;
}
void Test()
{
char* str=NULL;
str=GetMemory();
printf(str);
}
int main()
{
Test();
return 0;
}
int* f()
{
int * ptr;//野指针未初始化
*ptr=10;
return ptr;
}
void Getmemory(char** p,int num)
{
*p=(char*)malloc(num);
}
vloid Test()
{
char* str=NULL;
GetMemory(&str,100);
strcpy(str,"Hello");
printf(str);
//添加的解决释放代码
free(p);
p=NULL;
}
int main()
{
Test();
return 0;
}
void Test()
{
char* str=(char*)malloc(100);
strcpy(str,"hi");
free(str);//释放了堆区的内存,但是str中还保存着地址,但是使用的权限归操作系统,没权访问
if(str!=NULL)
{
strcpy(str,"hello");//错误,非法访问
printf(str);
}
}
int main()
{
Test();
return 0;
}
static
- 普通的局部变量是在栈区分配空间的,栈区的特点是在上面创建的变量出了作用域就销毁。
- 但是被static修饰的变量存放在数据段(静态区),数据段的特点是在上面创建的变量,直到程序结束才销毁
- 生命周期变长
typedef struct st_type
{
int i;
int a[0];//柔性数组成员
} type_a;
typedef struct st_type
{
int i;
int a[];//柔性数组成员
} type_a;
struct s
{
int n;
int arr[0];//大小未知
}
int main()
{
//期盼arr的大小是10个整数
struct S* ps=(struct S*)malloc(sizeof(struct S)+10*sizeof(int));
ps->n=10;
for(int i=0;i<10;i++)
{
ps->arr[i]=i;
}
//增加
struct S* ptr=(struct S*)realloc(ps,sizeof(struct S)+20*sizeof(int));
if(ptr!=NULL)
{
ps=ptr;
}
//使用
free(ps);
ps=NULL;
return 0;
}
struct S
{
int n;
int* arr;
}
int mian()
{
struct S* ps=(struct S*)malloc(sizeof(struct S));
if(ps==NULL)
reurn 1;
ps->n=10;
ps->arr=(int*)malloc(10*sizeof(int));
if(ps->arr==NULL)
{
return 1;
}
for(int i=0;i<10;i++)
{
ps->arr[i]=i;
}
//增加
int* ptr=relloc(ps->arr,20*sizeof(int));
if(ptr!=NULL)
{
ps->arr=ptr;
}
free(ps->arr);
ps->arr=NULL;
free(ps);
ps=NULL;
reuturn 0;
}
对比:
- 第一个好处是:方便内存释放
如果我们的代码是在一个给别人用的函数中,你在里面做了二次内存分配并把整个结构体返回给用户。用户调用free可以释放结构体,但是用户并不知道这个结构体内的成员也需要free,所以你不能指望用户来发现这个事。所以,如果我们把结构体的内存以及其成员要的内存一次性分配好了,并返回给用户一个结构体指针,用户做一次free就可以把所有的内存也给释放掉。- 第二个好处是:这样有利于访问速度
连续的内存有益于提高访问速度,也有益于减少内存碎片
#define INT_PTR int*
typedef int* int_ptr;
INT_PTR a,b;//int* a,b==int*a,(int)b;
int_ptr c,d//int*c,d==int*c,*d;
问题:那个变量不是指针?
答案:b