C语言 - malloc | calloc | realloc | memset | memcpy | memcmp

malloc

1 - 它是堆内存分配函数 ,其对应的返回值类型为 void* ,表示任意类型的指针都可以用它来开辟内存。参数为所需开辟的内存的大小,以字节为单位

int *p = malloc(sizeof(int)*4);// 开辟 4*int 个字节空间
for (int i=0; i<4; i++) {
    *(p+i)=arc4random()%21;
    printf("内存地址是%p 存储的数据是%d \n",p+i,*(p+i));
}

日志信息

2 - free 函数:堆区内分配函数开辟的存储区域要在使用结束后对其标记删除

free(p);

注:标记删除是指当前使用的存储区域可以被重新的分配给其他需要的数据,但是在重新分配之前它保存的原有数据会一直都在。为了防止野指针,在标记删除完以后需要将指针置空,表示这一段空间不再使用

p = NULL;

calloc

1 - 分配 n 个 size 字节的空间,并且对开辟的堆区空间初始化

int *p = calloc(4, sizeof(int));// 开辟 4 个整型空间
for (int i=0; i<4; i++) {
    printf("%d\n",*(p+1));
}

realloc

1 - 重新分配内存空间:根据给定已有空间的首地址来判断该空间后面是否有足够大的可用空间。如果存在可用的空间则顺序追加 newsize;如果没有可用的空间则在堆区中其他空间寻找 newsize 的空间开辟 ,并将原来的数据拷贝过去,同时释放掉原来空间的内存这也是 realloc 返回的地址有时跟传入的地址相同,而有时不同的原因

复制代码
 1 int *p = malloc(sizeof(int)*4); // 开辟 16 个字节的内存
 2 printf("%p\n",p);// 0x102886c20
 3     
 4 // 重新分配的空间 < 原来的空间大小
 5 int *q = realloc(p, 15);
 6 printf("%p\n",p);// 0x102886c20
 7 printf("%p\n",q);// 地址依旧是 0x102886c20
 8     
 9 // 重新分配的空间 > 原来的空间大小
10 int *k = realloc(q, 17);
11 printf("%p\n",k);// 地址改变 0x1028902d0
复制代码

memset

1 - 是对指定的堆区空间做初始化操作的函数,表示 p 指向的空间中有 n 个字节被初始化为 c

char buffer[] = "Hello world\n";
printf("%s\n", buffer); // 输出 Hello world
memset(buffer, '*', 5); // 前 5 个字节
printf("%s\n", buffer); // 输出 ***** world

注:运行崩溃

char *s = "Golden Kills";
memset(s,'G',6);
printf("%s",s);

原因:这里的 s 指向的是一段只读的内存,而 memset 又试图修改它,所以 crash

改正:将 char *s 改为 char s[ ] 

3 -  memset 是按照字节进行初始化的

1 long *q = malloc(200);
2 long a = 21;
3 q = memset(q, a, 64);// 前 64 个字节初始化为 a
4 
5 for (int i = 0; i < 200/8; i++) {
6     printf("%ld\n",*(q+i));
7 }

日志信息

memcpy

1 -  将第二个指针指向的堆区内存空间中指定的 n 个字节拷贝到第一个指针指向的内存空间的对应位置

复制代码
 1 int q[] = {11,22,33,44,55};
 2 int p[] = {88,99,66,77};
 3 
 4 memcpy(q, p, sizeof(int)*3); // 将 p 中前三个的数值拷贝到 q 中的前三个数值
 5 for (int i = 0; i < 5; i++) {
 6     printf("%d\t",*(q+i));
 7     if (4 - i ==0) {
 8         printf("\n");
 9     }
10 }
复制代码

日志信息

memcmp

1 - 将两个指针指向的堆区内存空间指定的字节数,按字节比较(做差)。如果结果为 0 则代表比较的空间相同

复制代码
1 int q[] = {11,22,33,44,55};
2 int p[] = {11,22,33,44};
3 int r[] = {111,222,333,444};
4 
5 int result1 = memcmp(q, p , sizeof(int)*4);
6 printf("%d\n",result1);// 输出 0
7 
8 int result2 = memcmp(q, r , sizeof(int)*4);
9 printf("%d\n",result2);// 输出 -100
复制代码

2 - 代码示例

① 有一字符串 h7dk43h5fd,其中包含有数字,请提取其中的数字。要求动态分配内存保存

复制代码
 1 char s[] = "h7dk43h5fd";
 2 int flag = 0;
 3 for (int i = 0;i<strlen(s); i++) {
 4     // 数字判断
 5     if (s[i]>='0' && s[i]<='9') {
 6         flag++;
 7         printf("%c",s[i]);
 8     }
 9 }
10 
11 printf("\nflag = %d\n",flag);
12 
13 // 开辟空间
14 char *number = malloc(sizeof(char) * flag);// 根据数字字符的个数来开辟堆内存空间
15 
16 int i = 0;
17 while (s[i] != '\0') {
18     
19     if (s[i] >= '0' && s[i] <= '9') {
20         
21         *number = s[i];// 赋值
22         number++;
23     }
24     
25     i ++;
26 }
27 printf("\n%s\n" ,number-flag);
28 free(number - flag);
29 number = NULL;
复制代码

② 输入 3 个学员的姓名,动态分配内存保存学员姓名,并在最后打印

复制代码
 1 char *names[3] = {0};
 2 for (int i = 0; i < 3; i++) {
 3     names[i] = malloc(255);// 开辟足够大的内存空间
 4 }
 5 
 6 for (int i = 0; i<3; i++) {
 7     printf("请输入第%d个名字:\n",i+1);
 8     scanf("%s",names[i]);
 9 }
10 for (int i=0; i<3; i++) {
11     printf("address %p ->content %s\n",names[i],names[i]);
12     free(names[i]);
13     names[i]=NULL;
14 }
复制代码

 注:malloc、realloc、calloc 只适用在堆内存;memset、memcmp、memcpy 适用于任何内存空间

posted on   低头捡石頭  阅读(77)  评论(0编辑  收藏  举报

编辑推荐:
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示