C语言教程(十八)内存管理

1. 简介

C语言中有两种比较重要的内存组织形式,一种是栈,另一种是堆。

栈是系统管理的内存,通常是用于函数运行,从函数调用开始系统开辟一块栈内存,然后压入参数、返回值等一系列操作,函数结束后系统将这块内存回收,这不需要我们操作,都是由系统自动完成的。

堆是程序员所管理的内存,通常用于为全局变量申请内存,内存使用完成后,还要程序员手动释放。动态内存分配函数也是主要针对堆内存来使用的。

2. malloc()与free()

malloc()函数用于在堆内存中分配一块指定大小的内存,它定义在标准库头文件<stdlib.h>中,函数原型如下。

void* malloc(size_t size)

该函数接受一个size_t类型的整数作为参数,表示指定要分配的内存字节大小。返回值类型是一个void指针,指向分配好的内存的首地址,如果分配失败,则返回NULL。

malloc()函数可以为任意数据类型分配内存,一开始不知道要存储的该内存的数据是什么类型,因此返回值类型只能是void指针,然后通过强转成具体的数据类型。

int *p = (int*) malloc(sizeof(int));

上面的示例是一般写法,用于给int类型的数据分配内存,对于处理分配失败的情况,可以做个判断。

int *p = (int*) malloc(sizeof(int));
if(p == NULL){
   printf("内存分配失败\n");
   return 1;
}

free()函数用于释放malloc()等函数所动态分配的内存,将这块内存归还给系统,这需要程序员手动调用这个函数。它定义在标准库头文件<stdlib.h>中,函数原型如下。

void free(void* ptr)

该函数接受一个void指针类型的参数,用于指向所要释放的内存的地址。所分配的内存一旦释放后,就不能再操作这块内存,否则会造成不可预知的后果;也不能进行二次释放。

int* p = (int*) malloc(sizeof(int));
if(p == NULL){
  printf("内存分配失败\n");
  return 1;
}
...
free(p);
p = NULL;

释放内存后,指针变量还是会指向原来的地址,为了避免野指针,所以把指针设置为NULL。

3. 动态分配函数

3.1 calloc()

calloc()函数也是用于分配动态内存,它与malloc()函数的区别是:calloc()函数不仅会分配内存,还会将所分配的内存全都初始化为0。它定义在标准库头文件<stdlib.h>中,函数原型如下。

void* calloc(size_t nitems, size_t size);

该函数接受两个参数,第一个参数是nitems,表示某种数据类型元素的个数,第二个参数是size,表示每个元素的字节大小。该函数返回一个void类型的指针,指向所分配的内存;如果分配失败,则返回NULL。

int* p = calloc(10, sizeof(int));

if(p == NULL){
   printf("内存分配失败");
}
free(p);
p = NULL;

注意:calloc()函数所分配的内存空间也需要调用free()函数手动释放。

3.2 realloc()

realloc()函数用于修改之前使用malloc()等函数已经分配过的内存,可进行大小调整。它定义在标准库头文件<stdlib.h>中,函数原型如下。

void* realloc(void* ptr, size_t size)

该函数接受两个参数,第一个参数是void类型的指针ptr,指向将要修改的内存块;第二个参数是size_t类型的szie,表示新的内存块的大小。该函数返回一个新的内存块的地址,如果分配失败,返回NULL。

int *p = malloc(sizeof(int) * 10);
p = realloc(b, sizeof(int) * 100);//修改内存大小

如果新的内存块大于原内存块,则不会对新增的内存进行初始化;如果新内存块小于原内存块,则会丢弃超出的内存。

如果第一个参数为NULL(空指针),则会分配一个新的内存块,那么和malloc()函数功能一样。如果第一个参数指向了已经分配的内存块且第二个参数为0的话,那么就会释放掉ptr所指向的内存块,并返回一个空指针NULL。

int *p = realloc(NULL, sizeof(int) * 100);

//等同于
int *p = malloc(sizeof(int) * 100);

//size为0
int *p = realloc(p, 0);//释放,返回空指针

3.3 memcpy()

memcpy()函数的作用是将一块内存的数据复制到另一块内存。它定义在标准库头文件<string.h>中,函数原型如下。

void *memcpy(void *dest,const void *source,size_t n)

该函数返回目的内存地址,即第一个参数;该函数接受三个参数:

  • void *dest:目的内存地址;
  • void *source:源内存地址;
  • size_t n:复制的字节数。

memcpy()函数可以复制任何类型的数据,还可以指定要复制的大小。

const char source[50] = "https://www.peiqiblog.com";
char dest[50];
memcpy(dest, source, sizeof(source));
printf("%s\n", dest);

3.4 memcmp()

memcmp()函数用于比较两个内存块的内容。它定义在标准库头文件<string.h>中,函数原型如下。

int memcmp(const void *str1,const void *str2,size_t n);

该函数会逐字节进行比较两个内存块的内容,该函数接受三个参数。

  • const void *str1:第一个内存块的指针;
  • const void *str2:第二个内存块的指针;
  • size_t n:指定比较的字节数。

该函数返回一个int类型的整数值,分三种情况。

  • 两者相同:返回值为0;
  • str1大于str2:返回一个正值;
  • str1小于str2:返回一个负值。
char* s1 = "abcde";
char* s2 = "abccc";
memcmp(s1, s2, 3);

注意,memcmp()函数遇到空字符时不会停止,而是要根据指定的字节数来确定。

觉得有帮助可以赞赏本文哦~万分感谢!
文章:C语言教程(十八)内存管理
作者:沛旗
链接:https://www.peiqiblog.com/article/4274/
版权声明::本博客站点所有文章除特别声明外,均采用 CC BY-NC-SA 4.0协议
转载请注明文章地址及作者哦~
暂无评论

发送评论(禁止发表一切违反法律法规的敏感言论) 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇