malloc在c语言中的用法(非常详细)
malloc() 是 C语言中的一个内存分配函数,用于在内存上分配指定大小的连续内存空间。
malloc() 函数是 C语言中动态内存管理的核心函数之一,使用 malloc() 函数分配的内存在函数返回后不会被自动释放,因此需要在适当的时候手动释放内存,以防止内存泄漏。
函数 malloc 的原型如下:
如果内存分配成功,那么 malloc() 函数将返回一个指向新分配内存的指针(void* 类型)。如果内存分配失败(例如,请求的内存大小超过可用内存),那么 malloc() 函数将返回 NULL。
我们一旦通过 malloc() 函数成功地申请了内存空间,就可以根据需要将返回的指针转为任意类型的指针。只要通过指针访问内存,就不能超过这段内存空间的大小。
下面是一个使用 malloc() 函数的示例:
同样,malloc(sizeof(double)) 申请了 8 字节的内存空间,若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。我们可以把这 8 字节的内存空间用于存储 double 类型的数据,只需通过赋值将 void* 转换为 double*,然后对 double* 类型的指针进行取值,接着将该值赋值给该指针。
在 C语言中,void * 可以通过赋值转换为其他类型的指针:
另外,一定要严格保证使用指针访问成功申请的内存空间时,不要超过申请时预定的空间大小,例如:
但是,若对 pDouble 指针使用取值运算符 *,将访问从首地址开始的 8 字节的内存空间,超出了申请时预定的 4 字节空间,这种做法可能导致程序崩溃。
若需要动态地创建一个有 10 个 int 元素的数组,那么需要申请 sizeof(int) * 10 字节的内存空间,或者也可以写成 sizeof(int[10])。
free() 是 C语言中用于释放之前通过 malloc() 函数分配的内存空间的内存释放函数。free() 函数也是 C语言中动态内存管理的核心函数之一。当不再需要使用动态分配的内存时,调用 free() 函数将内存归还给操作系统,以避免内存泄漏。
函数 free() 的原型如下:
注意事项:
以下是一个使用 malloc() 函数和 free() 函数的简单示例:
如果仅调用 malloc() 函数申请内存空间,而未调用 free() 函数释放内存空间,则成功申请的内存空间将保留直至程序结束。这期间程序所占用的内存空间会逐渐增大,直至无可分配空间,无法再成功申请内存空间。
下面展示了一个未释放内存的示例:
上面程序中,申请的内存空间首地址存储在指针 p 中,下一次新申请的内存空间首地址会覆盖上一次的首地址。由于没有保存内存空间的首地址,因此程序将无法再通过任何方式使用或释放这些内存空间,这种现象被称为内存泄漏。具有内存泄漏问题的代码若长时间运行,会导致程序所占用的内存空间逐渐增大,直至没有可分配的内存空间,并无法再成功申请内存空间。
malloc() 函数是 C语言中动态内存管理的核心函数之一,使用 malloc() 函数分配的内存在函数返回后不会被自动释放,因此需要在适当的时候手动释放内存,以防止内存泄漏。
函数 malloc 的原型如下:
void* malloc(size_t size);参数 size 表示要分配的内存大小,以字节为单位。通常使用 sizeof 操作符确定数据类型的大小。
如果内存分配成功,那么 malloc() 函数将返回一个指向新分配内存的指针(void* 类型)。如果内存分配失败(例如,请求的内存大小超过可用内存),那么 malloc() 函数将返回 NULL。
我们一旦通过 malloc() 函数成功地申请了内存空间,就可以根据需要将返回的指针转为任意类型的指针。只要通过指针访问内存,就不能超过这段内存空间的大小。
下面是一个使用 malloc() 函数的示例:
#include <stdio.h> #include <stdlib.h> int main() { int *pInt = NULL; pInt = malloc(sizeof(int)); double *pDouble = NULL; pDouble = malloc(sizeof(double)); *pInt = 123; *pDouble = 3.1415926; printf("%d %f", *pInt, *pDouble); return 0; }运行结果为:
123 3.141593
malloc(sizeof(int)) 申请了 4 字节的内存空间,若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。我们可以把这 4 字节的内存空间用于存储 int 类型的数据,只需通过赋值将 void* 转换为 int*,然后对 int* 类型的指针进行取值,接着将该值赋值给该指针。同样,malloc(sizeof(double)) 申请了 8 字节的内存空间,若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。我们可以把这 8 字节的内存空间用于存储 double 类型的数据,只需通过赋值将 void* 转换为 double*,然后对 double* 类型的指针进行取值,接着将该值赋值给该指针。
在 C语言中,void * 可以通过赋值转换为其他类型的指针:
int *pInt = NULL; pInt = malloc(sizeof(int)); double *pDouble = NULL; pDouble = malloc(sizeof(double));
另外,一定要严格保证使用指针访问成功申请的内存空间时,不要超过申请时预定的空间大小,例如:
double *pDouble = NULL; pDouble = malloc(sizeof(int)); *pDouble = 3.1415926;上面的代码申请了 sizeof(int),即 4 字节大小的空间。若申请成功,它将返回一个 void* 类型的指针,其数值为成功申请的内存空间的首地址。接着,我们把它转换为 double* 类型的指针,并赋值给 pDouble。
但是,若对 pDouble 指针使用取值运算符 *,将访问从首地址开始的 8 字节的内存空间,超出了申请时预定的 4 字节空间,这种做法可能导致程序崩溃。
若需要动态地创建一个有 10 个 int 元素的数组,那么需要申请 sizeof(int) * 10 字节的内存空间,或者也可以写成 sizeof(int[10])。
int *pArr = NULL; // 申请sizeof(int) * n,转换为int *使用 pArr = malloc(sizeof(int) * 10); // 给数组元素赋值 for (int i = 0; i < 10; i++) pArr[i] = i; // 输出数组元素 for (int i = 0; i < 10; i++) printf("%d ", pArr[i]);之前讨论的都是 malloc() 函数成功申请到内存的情况,作为一个稳健的程序应当也考虑失败的情况。若 malloc() 函数申请内存空间失败,它将返回 NULL。为 NULL 指针取值将导致程序崩溃。建议每次通过 malloc() 函数申请内存空间时都对返回值进行判断:
int *pInt = NULL; pInt = malloc(sizeof(int)); // 判断malloc函数是否成功申请了内存空间 if (pInt != NULL) { // 若不为NULL,则再次使用这个指针 *pInt = 123; printf("%d", *pInt); }
C语言释放内存空间
在使用 malloc() 函数申请内存空间并完成使用后,务必记得使用 free() 函数对这段内存空间进行释放。free() 是 C语言中用于释放之前通过 malloc() 函数分配的内存空间的内存释放函数。free() 函数也是 C语言中动态内存管理的核心函数之一。当不再需要使用动态分配的内存时,调用 free() 函数将内存归还给操作系统,以避免内存泄漏。
函数 free() 的原型如下:
void free (void* ptr);参数 ptr 表示指向要释放的内存块的指针。这个指针应该是之前由 malloc() 函数返回的指针。如果传递给 free() 函数的指针不是这个函数返回的指针,或者已经被释放过,将导致未定义行为。
注意事项:
- 如果 ptr 是 NULL,则 free() 函数不执行任何操作。
- 尝试释放已经释放过的内存(称为双重释放)将导致未定义行为。
- 使用 free() 函数释放内存后,不要再次访问已释放的内存区域。
以下是一个使用 malloc() 函数和 free() 函数的简单示例:
int *pInt = NULL; pInt = malloc(sizeof(int)); if (pInt != NULL) { *pInt = 123; printf("%d", *pInt); // 释放内存空间 free(pInt); }上述代码申请了 sizeof(int) 字节内存空间,用作 int 类型。内存使用完毕后,我们利用 free() 函数对内存空间进行释放。free() 函数的参数是 void* 类型的指针,而 void* 类型的指针可以接收任何类型的指针。因此,我们可以直接将 pInt 传递给 free() 函数,无须进行类型转换。
如果仅调用 malloc() 函数申请内存空间,而未调用 free() 函数释放内存空间,则成功申请的内存空间将保留直至程序结束。这期间程序所占用的内存空间会逐渐增大,直至无可分配空间,无法再成功申请内存空间。
下面展示了一个未释放内存的示例:
#include <stdio.h> #include <stdlib.h> int main() { while (1) { void* p = malloc(1024 * 1024); printf("%d\n", p); } return 0; }这种情况通常是由于申请了内存空间,但忘记释放内存空间导致的。应及时释放不再使用的内存空间。
上面程序中,申请的内存空间首地址存储在指针 p 中,下一次新申请的内存空间首地址会覆盖上一次的首地址。由于没有保存内存空间的首地址,因此程序将无法再通过任何方式使用或释放这些内存空间,这种现象被称为内存泄漏。具有内存泄漏问题的代码若长时间运行,会导致程序所占用的内存空间逐渐增大,直至没有可分配的内存空间,并无法再成功申请内存空间。