malloc 字符串

news/2024/12/5 4:33:12/

malloc内存管理机制:

​ 当首次使用malloc申请内存时,malloc会向操作系统申请内存,操作系统会直接给malloc分配33页(一页 = 4096字节)内存交给malloc管理。但是不意味着你可以越界访问,因为malloc可能会把使用权分给”其他人“,这就会导致脏数据。

每个内存块之间都会有一些空隙(4~12),这些空隙一些是为了内存数据对齐(加快读取),其中一定会有4个字节是用于记录malloc维护信息,这些维护信息决定了下次malloc分配内存的位置,以及借助这个维护信息计算出每个内存块的大小,当这些信息被破坏时,会影响下一次malloc和free的调用。

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

内存泄漏:

​ 内存无法再次使用,也无法被释放,而再次使用时只能重新申请,然后重复以上操作,最后导致日积月累后 系统中可以使用的内存越来越少。

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

如何避免:

​ 谁申请谁释放,谁知道谁释放

如何判断定位内存泄漏:(自己搜索一下)

​ 1、查看内存的使用情况 ps -aux

​ 2、使用代码分析工具(mtrace)来检查malloc和free的调用情况,是否有没释放的堆内存

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

内存碎片:

​ 已经释放但也无法继续使用的内存叫做内存碎片,是由于申请和释放时间不协调导致的,是无法避免只能尽量 减少。

​ 如何减少内存碎片:

​ 1、尽量使用栈内存

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

​ 3、尽量申请大块内存自己管理

内存清理函数:

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

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

​ s: 内存块的首地址

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

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

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

​ s: 内存块的首地址

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

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

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

堆内存来定义二维数组:

​ 指针数组:定义n*m的二维数组

​ 类型* arr[n];

int* arr[10] = {};
for(int i = 0; i<10; i++)
{arr[i] = malloc(20);//malloc(sizeof(类型)*m)可以定义不规则的二维数组 每行m可以不同
}for(int i = 0; i<10; i++)
{for(int j = 0; j<5; j++){printf("%d ",arr[i][j]);}printf("\n");
}
for(int i = 0; i<10; i++)
{free(arr[i]);arr[i] = NULL;
}

​ 数组指针:定义出了m*n的二维数组

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

​ 多维数组都是一维数组模拟的

int (*arrp)[5] = malloc(sizeof(int)*5*10);
for(int i = 0; i<10; i++)
{for(int j = 0; j<5; j++){printf("%d ",arrp[i][j]);}printf("\n");
}

练习: 计算出100~10000之间的所有素数,结果要储存在堆内存之中,不能浪费内存。

​ 1、计算出个数,然后一下申请出来,再计算后存储

​ 2、一边算一边扩充

#include <stdio.h>
#include <stdlib.h>int main(int argc,const char* argv[])
{int cnt = 0;int* p = NULL;for(int i = 100; i<10000; i++){int j = 2;for(j = 2; j < i; j++){if(i % j == 0){break;}}if(j == i){cnt++;p = realloc(p,cnt*4);p[cnt-1] = i;}}for(int i = 0; i<cnt; i++){printf("%d ",p[i]);}free(p);p = NULL;return 0;
}

字符串

字符:

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

​ ‘\0’ 0 空字符

​ ‘0’ 48

​ ‘A’ 65

​ ‘a’ 97

字符的输入:

​ scanf("%c",&ch); 等价于 ch = getchar();

字符的输出:

​ printf("%c",ch);

​ putchar(ch);

串:

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

​ 对于这种数据结构的处理都是批量性的,从开头位置开始直到结束标准为止。

字符串:

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

字符串的输入:

scanf %s 地址

​ 注意:不能接受空格!

char *gets(char *s);

​ 功能:输入字符串并且 能够接收空格!

​ 返回值:链式调用(把一个函数的返回值当作另一个函数的参数)

​ printf("%s",gets(memset(str,0,256)));

​ 注意:但是超出部分会压栈

char *fgets(char *s,int size, FILE *stream);fget(str,20,stdin);

​ 功能:可以设置输入的字符串的长度为size-1,超出部分不接收,会为’\0’预留位置

​ 注意:缺点是 如果输入的字符数不足size-1个,最后的’\n’也会被一起输出。

字符串的输出:

​ printf %s

int puts(const char *s);

​ 功能:输出一个字符串

​ 注意:会在末尾自动添加一个\n

​ 返回值:成功输出的字符个数

字符串的存在形式:

​ 字符数组:char str[10] = {‘a’,‘b’,‘c’};

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

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

​ 字符串字面值:“Hello World”

​ “由双引号包含的若干个字符”

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

const char* p = "Hello World";
printf("%d\n",p);
printf("%d\n","Hello World");//结果 = 字符个数+1

两个一模一样的字符串字面值在代码段中只会存储一份,所以地址相同

​ 常用方式: 字符数组[] = “字符串字面值”;

​ char str[] = “Hello”; (建议不设置)

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

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

练习:实现一个函数,判读字符串是否是回文串abccba

#include <stdio.h>
#include <stdbool.h>int size_int(char *str)
{int i = 0;while(str[i]){i++;}return i;
}char* restr(char *str,int len)
{int cnt = 0;for(int i=len-1; i>=cnt; i--){char t = str[i];str[i] = str[cnt];str[cnt++] = t;}return str;
}bool is_hui(char *str,int len)
{int cnt = 0;char str1[50];for(int i = 0; i<len; i++){str1[i] = str[i]; }restr(str,len);for(int i = 0; i<len; i++){if(str1[i] == str[i]){cnt++;}}return(cnt == len);
}
int main(int argc,const char* argv[])
{char str[50] = {};gets(str);char len = size_int(str);if(is_hui(str,len)){printf("是回文串");}else{printf("不是回文串");}
}

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

#include <stdio.h>long long int str_to_num(const char* str)
{long long int num = 0;int i = 0;while(*str && *str >='0' && *str <= '9'){num = num*10 + *str - '0';str++;}return num;
}int main(int argc,const char* argv[])
{char str[50];printf("%lld",str_to_num(gets(str)));
}

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

#include <stdio.h>char* restr(char *str,int len)
{int cnt = 0;for(int i=len-2; i>=cnt; i--){int t = str[i];str[i] = str[cnt];str[cnt++] = t;}return str;
}
int main(int argc,const char* argv[])
{char str[] = "Hello";int len = sizeof(str);printf("%s",restr(str,len));	}

练习:实现抽奖的功能,有十人的名单,随机顺序列出人名

#include <stdio.h>
#include <stdlib.h>
#include <time.h>int main(int argc,const char* argv[])
{	//char* str[10] = char str[10][10] = {"赛文","泰罗","迪迦","戴拿","高斯","塞罗","雷欧","杰诺","杰克","盖亚"};srand(time(NULL));int arr[10] = {};int cnt = 0;while(cnt < 10){int i =0;int	n = rand()%10;for(i = 0; i<cnt; i++){if(n == arr[i]){break;}}if(i == cnt){arr[cnt++] = n;}}for(int i = 0; i<10; i++){printf("%s\n",str[arr[i]]);}
}
#include <stdio.h>
#include <time.h>
#include <stdlib.h>int main(int argc,const char* argv[])
{srand(time(NULL));char* arr[6] = {"张三","李四","王五","赵六","刘七","周八"};for(int i=0;i<6;){int index = rand()%6;if(NULL != arr[index]){printf("第%d名:%s\n",i+1,arr[index]);arr[index] = NULL;i++;}}}

http://www.ppmy.cn/news/682877.html

相关文章

numpy.meshgrid()用法

用于生成网格点坐标矩阵 语法&#xff1a;X,Y numpy.meshgrid(x, y) 输入的x&#xff0c;y&#xff0c;就是网格点的横纵坐标列向量&#xff08;非矩阵&#xff09; 输出的X&#xff0c;Y&#xff0c;就是坐标矩阵。 import numpy as np import matplotlib.pyplot as pltx …

批量对热门文章发送评论,实现博客高效引流

许多人通过评论别人博客&#xff0c;提升自己博客的流量 随便点开一篇文章都可以找到相似话语 想拥有&#xff0c;百万流量指日可待了 先确定评论什么样的文章 选择平台首页文章&#xff0c;文章多&#xff0c;但杂乱选择排行榜文章&#xff0c;热度高&#xff0c;但数量有限…

2021年宜春民营企业百强排行榜:樟树市企业营收比重最大(附年榜TOP100详单)

榜单解读&#xff1a; 宜春市工商联发布了“2021宜春民营企业百强榜单”。榜单参照国际通行做法&#xff0c;以企业上一年度营业收入为依据进行排序&#xff0c;榜单企业总营收约为1797.97亿元。 依据榜单可知&#xff0c;仁和(集团)发展有限公司、江西济民可信药业有限公司这2…

程序员老黄历,你见过python版的吗

如&#xff1a;这样&#xff0c;还是这样 本来我是一直以为可以找到一个免费的api&#xff0c;结果找了好久也没找到&#xff08;这人肯定是脑子秀逗了&#xff09; 然后在百度找了一些例子&#xff0c;翻了一下源码&#xff0c;竟然是直接在源码维护的&#xff0c;而且量也很…

什么是 Deno,它与 Node.js 有何不同?

Node.js 是用于服务器和本地机器的事实上的 JavaScript 运行时。它很受欢迎&#xff0c;用途广泛&#xff0c;并得到了强大社区的支持。Deno 是一个更新的运行时&#xff0c;旨在解决 Node.js 的一些缺点。这就是 Deno 希望改进的地方。 基础 从历史上看&#xff0c;JavaScri…

k3cloud6.0文件服务器,K3Cloud系统集成配置详解

## K/3Cloud安装配置 1. 根据官方说明&#xff0c;正确安装K/3Cloud系统。安装完标准系统后需要安装易到家系统集成包&#xff0c;目前易到家系统集成包功能写入在了杰诺基础包中&#xff0c;杰诺基础包包含2部分&#xff0c;一个是产品许可包&#xff0c;一个是基础业务包&…

卡路里减肥助手隐私政策

隐私政策 最近更新日期&#xff1a;2021年12月30日 提示条款 您的信任对我们非常重要&#xff0c;我们深知个人信息对您的重要性&#xff0c;我们将按法律法规要求&#xff0c;采取相应安全保护措施&#xff0c;尽力保护您的个人信息安全可控。我们致力于维持您对我们的信任…

ArrayList常用方法

ArrayList 类是一个可以动态修改的数组&#xff0c;与普通数组的区别就是它是没有固定大小的限制&#xff0c;我们可以添加或删除元素。 ArrayList 继承了 AbstractList &#xff0c;并实现了 List 接口。 一、添加元素 ArrayList 类提供了很多有用的方法&#xff0c;添加元…