Menu Close

C语言动态存储分配

在数组一章中,曾介绍过数组的长度是预先定义好的,在整个程序中固定不变。C语言中不允许动态数组类型。

例如:

int n;
scanf(“%d”,&n);
int a[n];

用变量表示长度,想对数组的大小作动态说明,这是错误的。

但是在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。

对于这种问题,用数组的办法很难解决。为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。

常用的内存管理函数有以下三个:

1. 分配内存空间函数 malloc
调用形式:

ptr = (cast_type *) malloc (byte_size);
(类型说明符*) malloc (size)

功能:在内存的动态存储区中分配一块长度为”size”字节的连续区域。函数的返回值为该区域的首地址。“类型说明符”表示把该区域用于何种数据类型。(类型说明符*)表示把返回值强制转换为该类型指针。“size”是一个无符号数。

例如:

pc=(char *)malloc(100);

表示分配 100 个字节的内存空间,并强制转换为字符数组类型,函数的返回值为指向该字符数组的指针,把该指针赋予指针变量 pc。

2. 分配内存空间函数 calloc

calloc 也用于分配内存空间。

调用形式:

ptr = (cast_type *) calloc (n, size);
(类型说明符*)calloc(n,size)

功能:在内存动态存储区中分配 n 块长度为“size”字节的连续区域;函数的返回值为该区域的首地址;当内存空间分配后,所有字节初始化为零。

每当分配内存空间错误(例如内存不足)时,都会返回空指针。

calloc 函数与 malloc 函数的区别仅在于一次可以分配 n 块区域。

例如:

ps=(struet stu*)calloc(2,sizeof(struct stu));

其中的 sizeof(struct stu)是求 stu 的结构长度。因此该语句的意思是:按 stu 的长度分配 2 块连续区域,强制转换为 stu 类型,并把其首地址赋予指针变量 ps。

3. 释放内存空间函数 free

调用形式:

free(void*ptr);

功能:释放 ptr 所指向的一块内存空间,ptr 是一个任意类型的指针变量,它指向被释放区域的首地址。被释放区应是由 malloc 或 calloc 函数所分配的区域。

例1.  – 分配一块区域,输入一个学生数据

main()
{
 struct stu
 {
    int num;
    char *name;
    char sex;
    float score;
 } *ps;
 
   ps=(struct stu*)malloc(sizeof(struct stu));
   ps->num=102;
   ps->name="Zhang ping";
   ps->sex='M';
   ps->score=62.5;
   printf("Number=%d\nName=%s\n",ps->num,ps->name);
   printf("Sex=%c\nScore=%f\n",ps->sex,ps->score);
   free(ps);
}

 

本例中,定义了结构 stu,定义了 stu 类型指针变量 ps。然后分配一块 stu 结构体内存区,并把首地址赋予 ps,使 ps 指向该区域。再以 ps 为指向结构的指针变量对各成员赋值,并用printf 输出各成员值。最后用 free 函数释放 ps 指向的内存空间。

整个程序包含了申请内存空间、使用内存空间、释放内存空间三个步骤,实现存储空间的动态分配。

例2.动态分配内存空间

#include <stdlib.h>
int main()
{
    int *ptr;
    ptr = malloc(15 * sizeof(*ptr)); /* a block of 15 integers */
    if (ptr != NULL) {
      *(ptr + 5) = 480; /* assign 480 to sixth integer */
      printf("Value of the 6th integer is %d",*(ptr + 5));
    }
}

  1. 请注意,当以后将* ptr声明类型转换为其他数据类型时,使用sizeof(* ptr)代替sizeof(int)是为了使代码更有兼容性;
  2. 如果内存不足,分配可能会失败。 在这种情况下,它将返回NULL指针。 因此,您应该包括用于检查NULL指针的代码;
  3. 请记住,分配的内存是连续的,可以将其视为数组。 我们可以使用指针算法来访问数组元素,而不是使用方括号[]。 我们建议使用+来引用数组元素,因为使用增量++或+ =会更改指针存储的地址。

例3.用malloc分配一个整型数组指针,并赋值给第二个整数

  
#include <stdio.h>
int main()
{
    int* ptr = malloc(10 * sizeof(*ptr));
    if (ptr != NULL)
    {
       *(ptr + 2) = 50;
       printf("Value of the 2nd integer is %d",*(ptr + 2));
    }
    free(ptr);
}
  

例4.动态分配内存实现自然数加法

  #include <stdio.h>
    int main()
    {
        int i, * ptr, sum = 0;
        ptr = calloc(10, sizeof(int));
        if (ptr == NULL) {
            printf("Error! memory not allocated.");
            exit(0);
        }
        printf("Building and calculating the sequence sum of the first 10 terms \ n ");
        for (i = 0; i < 10; ++i)
        {
            * (ptr + i) = i;
            sum += * (ptr + i);
        }
        printf("Sum = %d", sum);
        free(ptr);
        return 0;
    }

 

calloc与malloc:主要区别

calloc函数通常比malloc函数更合适,更高效。 虽然这两个函数都用于分配内存空间,但calloc可以一次分配多个块。 您不必每次都请求存储块。

calloc函数用于需要更大存储空间的复杂数据结构中。calloc函数分配的内存块始终初始化为零,而在malloc中,它始终包含垃圾值。

4. Realloc 函数

使用realloc()函数,可以将更多的内存大小添加到已分配的内存中。 它扩展当前块,同时保留原始内容。 realloc代表内存的重新分配。

realloc也可以用来减小先前分配的内存的大小。

语法:

ptr = realloc (ptr,newsize);

上面的语句在变量newsize中分配具有指定大小的新内存空间。 执行完函数后,指针将返回到存储块的第一个字节。 新的大小可以大于或小于以前的内存。

我们不能确定新分配的块是否将指向与先前存储块相同的位置。 此功能将在新区域中复制所有先前的数据。 它确保数据将保持安全。

例5.

  #include <stdio.h>
int main ()
{
   char *ptr;
   ptr = (char *) malloc(10);
   strcpy(ptr, "Programming");
   printf(" %s,  Address = %u\n", ptr, ptr); 
   ptr = (char *) realloc(ptr, 20); //ptr is reallocated with new size
   strcat(ptr, " In 'C'");
   printf(" %s,  Address = %u\n", ptr, ptr);
   free(ptr);
   return 0;
}

每当重新分配导致操作失败时,它都会返回空指针,并且先前的数据也将被释放。

除教程外,本网站大部分文章来自互联网,如果有内容冒犯到你,请联系我们删除!

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Leave the field below empty!

Posted in C语言教程

Related Posts