C语言的动态内存管理

目录

最近参加的几次C/C++笔试,考查最多的有两点:万年必考的指针和C的malloc、memcpy等函数。

对于malloc和memcpy,最典型的就是考程序改错,基本程序改错题都有关于这两者的错误。还有见过某道简答题:

C中的malloc、free与C++中new、delete区别

考查C++内存管理与C的区别。更进一步,则可以考C与C++的区别(某次面试提的,我只想到了上面这部分,显然还有更多区别)。
多年不用C,都忘得差不多了,再重新学习一下动态内存分配的函数。

Dynamic memory management (cstdlib)

malloc

[cpp]void * malloc ( size_t size );[/cpp]
申请一块空间,返回开始地址。参数为空间的字节数,一般需要用到sizeof运算符计算具体的字节数。申请的空间没有被初始化,与calloc不同。
注意返回 void* 指针,使用时一般需要转换到其它具体的指针类型。如
[cpp]int* arr = malloc(15*sizeof(int));[/cpp]

calloc

[cpp]void * calloc ( size_t num, size_t size );[/cpp]
为num个元素的数组申请一块空间,每个元素大小为size字节,并把所有位均设为0。同上,返回指向起始位置的void*指针,需要转型。

realloc

[cpp]void * realloc ( void * ptr, size_t size );[/cpp]
将ptr指向的内存块大小改变成size大小,增加或减少都可以。若原地连续内存块够用,则直接扩展,若原地连续内存块不够,则将内存块移到一个新的位置。保留原始数据,数目由原始大小和目标大小的最小值决定。即减少空间直接截断;增加空间,数据不变,新的位置内容不确定。
ptr为NULL,等同于malloc。
size为0,相当于free,返回NULL指针。(真的会有人这么用么?)
返回值
成功,返回void*。
失败,返回NULL指针,原始内存块保持不变。

free

[cpp]void free ( void * ptr );[/cpp]
释放有上面三个函数申请的空间,以便再一次申请使用。但free不清除ptr上的数据(?),ptr依然指向内存块,只不过已经无效了。

Copying

****memcpy

[cpp]void * memcpy ( void * destination, const void * source, size_t num );[/cpp]
复制内存块。将从source起始的num字节直接拷贝到destination起始的内存块中,与内存块的类型无关,是数据的位拷贝(binary copy)。
为了防止移除(overflow),需要保证source和destination至少有num字节,并没有重叠。重叠区域可使用memmove。
返回destination。

memmove

[cpp]void * memmove ( void * destination, const void * source, size_t num );[/cpp]
移动内存块。允许内存块重叠。其它与memcpy相似。
可以看下memmove的源代码,我没找到,只有网上的近似代码。

strcpy

[cpp]char * strcpy ( char * destination, const char * source );[/cpp]
从source拷贝C字符串到destination,包括字符串结尾的空字符。返回destination。
为了防止溢出,destination至少需要source字符串的大小,并与source不重叠。

strncpy

[cpp]char * strncpy ( char * destination, const char * source, size_t num );[/cpp]
从source拷贝num字符到destination。
如果source的C字符串长度小于num,则将destination用0补齐。destination不保证以NULL字符结束,但若source字符串长度小于num,则destination以NULL字符结束。

Other

memset

[cpp]void * memset ( void * ptr, int value, size_t num );[/cpp]
填充内存块。
将ptr内存块的前num字节设置为特定值value(将value解释成unsigned char,涉及有符号数到无符号数的转型)。
返回ptr。