07-内存管理

  • 作用域: 变量起作用的范围
  • 变量
    局部变量 在{}范围之内定义的变量
    auto int a; auto可加可不加

静态局部变量 在{}范围之内定义的变量,前面加上static修饰变量
static int a;

全局变量 在函数之外定义的变量
静态全局变量
在函数之外定义的变量 ,加上static修饰的变量
static int a;

生命周期:
什么时候开辟空间(出生),释放空间(死亡),这个过程叫生命周期

  • 局部变量
    a> 作用域 在定义变量的{}之内有效
    b>生命周期 程序运行至变量定义处开辟空间,所在的函数结束之后释放空间
    c>未初始化的值 随机

  • 静态局部变量
    a>作用域 在定义变量的{}之内有效
    b>生命周期 执行main函数之前就已经开辟空间,程序结束之后才释放空间
    c>未初始化的值 0

  • 全局变量
    a>作用域 整个工程,所有文件
    b>生命周期 执行main函数之前就已经开辟空间,程序结束之后才释放空间
    c> 未初始化的值 0

  • 静态全局变量
    a>作用域 当前文件
    b> 生命周期 执行main函数之前就已经开辟空间,程序结束之后才释放空间
    c> 0

    注意: 在.h中,全局变量只声明不定义,定义只放在.c文件

变量重名问题

考虑作用域的前提下,遵循就近原则
![[Pasted image 20230817132440.png]]

静态函数
斤太含糊就是在函数定义时加上static修饰的函数,静态函数只可以被当前文件函数使用
static void fun(){}
普通的函数没有加上任何修饰,就是全局函数,整个工程可以调用

程序内存分布

![[Pasted image 20230817141945.png]]

memset

#include <string.h>
/*
void *memset(void *s, int c, size_t n);
功能:将s的内存区域的前n个字节以参数c填入
参数:
       s:需要操作内存s的首地址
       c:填充的字符,c虽然参数为int,但必须是unsigned char , 范围为0~255
       n:指定需要设置的大小
返回值:s的首地址
*/
int main()
{
        int  a =10;
        //a = 0;  ->  memset()
        memset(&a,0,sizeof(a));
        //printf("a=%d\n",a);
        char buf[10] = "";
        strcpy(buf,"hello");
        printf("%s\n",buf);
        memset(buf,0,sizeof(buf));
        printf("%s\n", buf);
        //将前9个字符置为'a'
        memset(buf,'a',sizeof(buf)-1);
        printf("%s\n", buf);
}

内存拷贝 memcpy,字节为单位

/*
#include <string.h>
void *memcpy(void *dest, const void *src, size_t n);
功能:拷贝src所指的内存内容的前n个字节到dest所值的内存地址上。
参数:
       dest:目的内存首地址
       src:源内存首地址,注意:dest和src所指的内存空间不可重叠,可能会导致程序报错
       n:需要拷贝的字节数
返回值:dest的首地址
*/
int main()
{
        char str1[128] = "";
        char str2[128] = "abc\0def\0dadfa";
        //memcpy(str1,str2,10*sizeof(char));
        strncpy(str1, str2, 10 * sizeof(char));
        for (int i = 0; i < 10; i++)
        {
               printf("%d ",str1[i]);
        
        }
        system("pause");
        return 0;
}
int main04()
{
        //将数组a中前5个元素拷贝至数组b中
        int  a[10] = {1,2,3,4,5,6,7,8,9,10};
        int  b[10] = { 0 };
        //a = b;
        memcpy(b,a,sizeof(int)*5);
        for (int i = 0; i < sizeof(b) / sizeof(b[0]); i++)
        {
               printf("%d ",b[i]);
        
        }
        system("pause");
        return 0;
}

memcmp 内存比较

/*
#include <string.h>
int memcmp(const void *s1, const void *s2, size_t n);
功能:比较s1和s2所指向内存区域的前n个字节
参数:
       s1:内存首地址1
       s2:内存首地址2
       n:需比较的前n个字节
返回值:
       相等:=0
       大于:>0
       小于:<0
*/
int main()
{
        char num1[] = { 1,0,3,4,5,6,7 };
        char num2[] = { 1,0,3,6,5,6,7 };
        char str1[] = "dbakf\0afnafa";
        char str2[] = "dbakf\0bfnafa";
        //printf("%d\n", memcmp(num1,num2,7*sizeof(char)));
        //printf("%d\n", strncmp(num1, num2, 7 * sizeof(char)));
        printf("%d\n", memcmp(str1, str2, sizeof(str1)));
        printf("%d\n", strncmp(str1, str2, sizeof(str1)));
        system("pause");
        return 0;
}

malloc 向堆区申请空间, free释放空间

/*
#include <stdlib.h>
void *malloc(size_t size);
功能:在内存的动态存储区(堆区)中分配一块长度为size字节的连续区域,用来存放类型说明符指定的类型。分配的内存空间内容不确定,一般使用memset初始化。
参数:
       size:需要分配内存大小(单位:字节)
返回值:
成功:分配空间的起始地址
失败:NULL

free()
#include <stdlib.h>
void free(void *ptr);
功能:释放ptr所指向的一块内存空间,ptr是一个任意类型的指针变量,指向被释放区域的首地址。对同一内存空间多次释放会出错。
参数:
ptr:需要释放空间的首地址,被释放区应是由malloc函数所分配的区域。
返回值:无
*/

内存泄漏

只申请,不释放
内存污染: 向没有申请过的内存空间写入数据
![[Pasted image 20230817195054.png]]

返回变量的地址

只有普通局部变量的地址不可以哦返回,因为普通局部变量在所在的函数结束后就被释放。
静态局部、全局、静态全局,这些变量,只要程序不退出,就不会释放,所以这些变量的地址是可以返回操作的

int a = 10;
int * fun()
{
        //int a = 10;
        //static  int  a = 10;
        a *= 10;
        return &a;
}
int main()
{
        int * p = fun();
        *p = 2000;//  p所指向的空间没有释放(静态局部变量),则可以操作这块内存,
        //释放不可以操作(普通局部)
        printf("%d\n",*p);
        system("pause");
        return 0;
}

返回堆区的地址

堆区的地址是可以被返回,只要没被释放

char *fun4()
{
        char *q = malloc(100);
        return q;//ok  堆区的地址是可以返回的,堆区函数结束不会被释放
}
int main()
{
        char *p = fun4();
        //p = "hello";
        strcpy(p,"hello");
        free(p);//err  p并没有指向堆区,而是指向文字常量区"hello"
        system("pause");
        return 0;
}

在这里插入图片描述

典型错误,通过函数的值传递,不能改变实参的值,指针

注意: 能不能返回这个地址,需要看这个地址所指向的空间有没有被释放:

![[Pasted image 20230817203005.png]]

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值