C-class Week2.Day10

堆:

​ 当首次使用malloc申请内存,系统就会分配一个33页的内存、33*1024 -2 是可以用的位置 最后四个字节不能用。

这33页由malloc管理,但是使用者也有权使用,只要在33页范围内都行。这种越界访问存在隐患会产生脏数据,

如果再向malloc申请,如果小于33页。则不向系统申请,在33页里面的寻找合适的空间。

​ 每个内存块之间、都会有一些空隙4-12个字节。这些空隙一些是为了数据对齐、其中一定会有四个字节用于malloc的

维护信息,这些维护信息决定了下次malloc分配内存的位置,以及借助这个维护信息计算出每个内存块的大小,当这些

信息被破坏时,会影响下一次malloc的操作。注意malloc有[-1] 来储存放在0位置的维护信息。

使用堆内存要注意的问题:

内存泄漏:

​ 内存无法继续再次使用,也无法被释放。导致内存空间不断减少,而再次使用时只能重新申请,然后重复以上操作。

日积月累后系统中可以使用的内存越来越少。

注意:

​ 程序一旦结束后,属于该程序的所有资源都会被操作系统回收。

如何尽量避免:

​ 谁申请的,谁释放

​ 谁知道该释放,谁释放

如何判断定位内存泄漏:

​ 1、windows下使用任务管理器,查看内存的使用情况 linux下–ps命令–(ps-aus)查看内存进程等

​ 2、下载malloc检查工具、检查malloc-free的对应关系,能检测出哪个malloc没有free

​ 3、包装malloc,free函数,记录申请和释放内存的信息到日志中。

内存碎片:

​ 已经释放但也无法继续使用的内存,申请和释放的时间不协调导致的,是无法预测的且无法避免的,

只能减少。

如何减少内存碎片:

​ 1、尽量使用栈内存,少使用堆内存

​ 2、不要频繁的申请和释放内存

​ 3、尽量申请大块内存,由程序员手动管理

内存清理函数:

void bzero(void *s, size_t n):
	   #include <strings.h>
       void bzero(void *s, size_t n);

​ s:需要清除的内存首地址

​ n:要清理内存块的字节数

void bzero(void *s, size_t n):
       #include <string.h>
       void *memset(void *s, int c, size_t n);

​ 功能:把内存块按字节设置为字符c

​ s:内存块的首地址

​ c:想要设置的字符的ASCII码值

​ n:设置的内存块的字节数

​ 返回值:返回设置成功后的内存首地址

共享地址金典题目
	void creat(int *p,int size)
	{
		p = malloc(size);
		if(p == NULL)
		{
			perror("malloc");
		}
	}
	
	int main()
	{
		int *p = NULL;
		creat(&p,40);//这里并没有给当前函数的*p赋值,所以*p依旧是NULL,跨函数共享指针变量,需要传递二级指针
		for(int i=0;i<10;i++)
		{
			p[i] = i;
			printf("%d ",p[i]);
		}
		free(p);
		p = NULL;
	}
	
	段错误!!!!!!
	
	void creat(int **p,int size)
	{
		*p = malloc(size);
		if(*p == NULL)
		{
			perror("malloc");
		}
	}
	
	int main()
	{
		int *p = NULL;
		creat(&p,40);
		for(int i=0;i<10;i++)
		{
			p[i] = i;
			printf("%d ",p[i]);
		}
		free(p);
		p = NULL;
	}

堆内存来定义二维数组:

指针数组:

​ 定义了一个n*m的二维数组,每一行个数可以不同,可以自定义不规则数组

​ 类型* arr[n];

​ int *arr[10];

	int main()
	{
		int *arr[10] = {};
		for(int i=0;i<10;i++)
		{
			arr[i] = malloc(sizeof(int)*5);
		}
		
		for(int i=0;i<10;i++)
		{
			for(int j=0;j<5;j++)
			{
				printf("%d ",arr[i][j]);
			}
		}
		for(int i=0;i<10;i++)
		{
			free(arr[i]);
			arr[i] = NULL;
		}
	}
数组指针:

​ 注意:在物理上是不存在二维数组的,都是用一维数组模拟的。由于每行的元素限定,所以不可以自定义数组。

​ 类型 ( *arrp)[ n ] = malloc(sizeof(int)*n*m)

	int main()
	{
		int (*arrp)[5] = malloc(sizeof(int)*5*10)// 10row 5col 5 5 5 5 5 5 5 5 5 5 = 50 in on row! 10times
		for(int i=0;i<10;i++)
		{
			for(int j=0;j<5;j++)
			{
				cout<<arrp[i][j];
			}
			cout<<endl;
		}
	}

练习:计算100-10000之间所有素数 结果储存在堆内存中,并且不能浪费内存。

​ 1、算出来,申请这么多个数

​ 2、一边算一边存

int main()
{
	int *arr = NULL,count = 0;
	for(int i=100;i<10000;i++)
	{
		if(is_prime())
		{
			arr = relloc(arr,sizeof(int)*(count+1));
			arr[count++] = i;
		}
	}
	for(int i=0;i<count;i++)
	{
		printf("%d ",arr[i]);
	}
	free(arr);
	arr = NULL;
	return 0;
}

字符串:

字符:char

​ 在计算机中字符是以整数形式存储在内存中,当需要时显示字符时,会根据ASCII码表中对应的关系来显示符号或者图案。

​ ’ \0’ —0 空字符 ‘0’ —48 ‘A’ —65 ‘a’ —97

字符的输入:
	char ch;
	scanf("%c",&ch);
	ch = getchar();
字符的输出:
	printf("%c",ch);
	putchar(ch);
串:

​ 是一种数据结构,是由一组连续的若干个相同类型的数据组成,末尾有结束标志。这个结束标志由自己定义,对于这种数据结构

​ 的处理都是批量性的,从开头位置开始到结束标志为止。

	int arr[] = {123,13,23,5,6,8,9,1,~0};
	for(int i=0;arr[i] != ~0;i++)
	{
		show_arr(arr);
	}
字符串:string

​ 由字符组成的串形结构,结束标志是 ‘\0’

​ 字符串的输入:

	char str[256]={};
	scanf("%s",str);
	不能接受空格!遇到空格默认是回车
    gets(str);
	可以接受空格!遇到回车才结束
    返回值:链式调用(把一个函数的返回值当做另一个函数的参数!)
    printf("%d",gets(str));
	
	char *fgets(char *s,int size,File *stream);
	功能:可以设置输入的字符串的长度为size-1,超出部分不接受,会为'\0'预留位置。
    输入的字符数不足size-1个最后的'\n'也会被接受到。
    char str[20] = {};
    fgets(str,20,stdin)

​ 字符串的输出:

	printf("%s",str);

	int puts(const char *s);
	功能:输出一个字符串,自动添加换行符。
    返回值:成功输出的字符个数。
字符串的存在形式:
字符数组:

​ char str[10] = {‘a’,‘b’,‘c’};

​ 由char类型组成的数组,会为’\0’预留位置

​ 使用的是栈内存,因此数据可以修改

字符串字面值 :

​ “Hello World”

​ “由双引号包含的若干个字符”,会在结尾隐藏一个\0

​ 字符串字面值是以地址形式存在的,数据存储在代码段text中,如果修改会产生段错误

​ const char *p = “字符串字面值”

​ sizeof(“strstr”) = 7 结果= 字符个数+1;

​ 两个一模一样的字符串字面值在代码中只存储一份

常用方式 :

​ 字符数组[ ] = “字符串字面值!”;

​ char str[] = “hello”;

​ 会自动为’\0’ 预留位置。

​ 注意:赋值完成后字符串就存在了两份,一份存储在代码段,一份在栈内存(可修改)!

练习1:实现一个函数判断字符串是否是回文串

练习2:实现一个函数,把由数字字符组成的字符串转换为整数 “1234”—1234

练习3:实现一个函数把字符串逆序abcd,把字符串逆序输出

练习4:实现一个密码登录功能

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值