数据分析——动态分配内存、结构体


一、动态分配内存

申请堆区的空间,需要手动申请,手动释放

如果直接定义在代码中的变量,是系统默认分配栈区的空间,栈区空间自动申请,生命周期结束自动释放。

需要用到头文件#include

malloc和free一定成对出现

1.1 malloc

函数原型:
void *malloc(size_t size);   //有参数有返回值函数
功能:
从堆区申请size个字节,并将这一片空间的首地址返回给主调函数处
所以返回值为void*方便强转
void*表示万能指针(可以被强转成任何类型的指针)
使用:
int *p = (int*)malloc(sizeof(int));  //赋值运算符右侧的(int*)表示将malloc申请的首地址,强转成int类型
//让int*类型的指针p指向malloc申请的(sizeof(int))大小的堆区空间
//int *p = (int*)malloc(4);

1.2 free

功能:释放堆区的内存空间

函数原型:
    void free(void *ptr);
返回值:无
参数:要释放的堆区空间的首地址
堆区申请空间一定要使用free释放防止内存泄漏
一般释放完堆区内存后,会将原本指向堆空间的指针指向NULL

1.3 指针的强转

因为不同数据类型的指针的大小相同,所以指针之间的强转是安全的

但是会改变指针的偏移量

int *p; 
char *p1=(char*)p; 
上面的强转过程不会造成数据的丢失,但是如果p本身已经指向int类型数据,使用p1访问该数据时,可能只访问到低字节的数据

1.4 堆空间的地址作为指针函数的返回值

#include <stdio.h>
#include <stdlib.h>
int *func()
{
    int *p=(int*)malloc(4);
    *p=49;
    return p;
}
int main(int argc, const char *argv[])
{

    int *ret=func();  //因为func的返回值为堆空间申请的内存,不手动释放不会被回收    
    printf("%d\n",*ret);
    printf("%p\n",ret);
 //释放堆内存
 free(ret);
    return 0;
}

1.5 悬空指针

指针指向一片地址,但是对这片地址没有使用权,间接访问可能会发生段错误

1.5.1 指向已经堆放的空间

#include <stdio.h>
#include <stdlib.h>
int *func()
{
    int *p=(int*)malloc(4);
    *p=49;
    return p;
}
int main(int argc, const char *argv[])
{

    int *ret=func();  //因为func的返回值为堆空间申请的内存,不手动释放不会被回收    
    printf("%d\n",*ret);
    printf("%p\n",ret);
 //释放堆内存
 free(ret);
 printf("%p\n",ret);  //释放前后,ret的值不变
 //一般释放完堆区内存后,会将原本指向堆空间的指针指向NULL
 ret=NULL;
    return 0;
}

1.5.2 指向已经被回收的空间

#include <stdio.h>
int *func()
{
    int a=90;
    int *p=&a;
    return p;   //这种方式返回编译不会报警告,因为智能识别到p是局部变量,返回p的值
}
int main(int argc, const char *argv[])
{
    int *ret=func();  //ret是一个悬空指针,指向已经被回收的栈空间的地址
    printf("%d\
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值