了解动态内存分配

Understanding dynamic memory allocation

我是 C 编程的初学者。最近有人教我如何使用 malloc,但我认为我不太了解它。比如为什么它实际上需要 void * 或任何类型转换?为什么语法本身在void *malloc(size_t size)中有(void *)。而分配给malloc函数的变量又是如何知道内存块从哪里开始的呢? malloc函数return分配内存块后的地址或其他东西吗?

在 class 我们的教授给了我们这个程序。我也了解 2d 内存分配的工作原理。

#include<stdio.h>
#include<conio.h>
void main(void)
{
    int *studentInfo=NULL,i=1,j=10,k=0,l=0;
    //int *studInfo[10];
    int memLoc=0;
    clrscr();

    printf("How many Student Information You want to store:");
    scanf("%d",&j);
    printf("How many Subject Marks per student You want to store:");
    scanf("%d",&k);
    studentInfo=(int *)malloc(j*k*sizeof(int));

    //memLoc=0;
    for(l=0;l<j;l++)
    {
        printf("Enter Marks for %dth Student",l+1);
        for(i=0;i<k;i++)
        {
            printf("\nEnter Marks for Subject %d:",i+1);
            scanf("%d",studentInfo+(l*j)+i);
        }
    }
    //3 students and 3 subjects
    //memory allocated=3*3*2=18
    //0,1,2 student 0*no of students
    //3 4 5 student 1
    //6 7 8 student 2

    printf("\nInformation you Entered\n");
    for(l=0;l<j;l++)
    {
        printf("Makrs of Student %d:",l+1);
        for(i=0;i<k;i++)
            printf("\t%d",*(studentInfo+(l*j)+i));
        printf("\n");
    }

    //*(studentInfo)=10;
    //*(studentInfo+1)=20;
    //*(studentInfo+2)=30;
    //printf("%d\n",sizeof(studentInfo));
    //printf("%d\n",*(studentInfo));
    //printf("%d\n",*(studentInfo+i++));
    //printf("%d\n",*(studentInfo+i++));


    free(studentInfo);
    getch();
}

在这里,我们将 studentInfo 指针分配给 malloc 函数,对吗?那么... studentInfo 怎么知道内存块的地址是 USA 而不是 Antarctica?而且我知道用其他数据类型对 malloc 进行类型转换不是一个好习惯。但是为什么(int *)。为什么 malloc 需要一个指针??如果 malloc 需要一个指针,这意味着它正在 returning 一个地址,对吗?我问过我的朋友,他说没有 malloc 没有 return 任何东西。还有一件事是我们需要将类型转换放在括号中吗?

请用非常简单的术语解释。 谢谢。

Why does the syntax itself have (void *) in void *malloc(size_t size).

因为 malloc 是一个函数,而函数有一个 return 类型。这表明此函数 return 是此特定类型。所以(void *)表示mallocreturn一个void *.

Does the malloc function return an address or something after it has assigned a memory block?

Malloc 将指定大小的内存分配到堆中,并且 return 是指向该分配内存的指针。

In this we are assigning the studentInfo pointer the malloc function right? So... how does studentInfo know that the address of the memory block is USA and not Antarctica??

不完全是。 studentInfo 未分配 malloc 函数,但 studentInfo 指向由 malloc 编辑的指针 return。这是 studentInfo 现在指向分配的内存。

Why does malloc need a pointer??

malloc 不需要指针。它需要您要分配的内存量作为参数。

您无需在此处进行类型转换,因为 void * 会自动升级。

And one more thing is it necessary that we need the typecast to be in brackets?

是的,这就是类型转换的语法。没有括号会导致编译错误

malloc returns void* 因为 malloc 不仅分配 int,它还可以分配浮点数,双倍偶数结构等。返回指针的原因是因为它可以在堆中分配这么多内存,堆比堆栈大,如果分配的内存对于堆栈来说太大了,你会收到一个错误(可能是Whosebug)+如果我们只能复制它的地址并通过指针引用它,那么复制内存是没有意义的.而void *是一种特殊的类型,无论是什么类型的地址都可以赋值。是的,你需要转换它,如果你不这样做,那么编译器会给你一个错误

malloc 函数调用分配了一个足够大的内存块来容纳 j*k int 对象和 returns 该块第一个元素的地址 - 即地址值分配给 studentInfo,给我们这样的东西:

             int *       int
             +–––+       +–––+
studentInfo: |   | ––––> |   |
             +–––+       +–––+
                         |   |
                         +–––+
                          ...

因此,studentInfo 指向(存储地址)该序列中的第一个 int 对象。

代码中 malloc 调用之前的 (int *)cast - 它表示“处理以下表达式的结果(返回的值通过 malloc) 作为 int *,或指向 int 的指针。"

只有两种情况你 必须 转换 malloc 的结果:

  • 您正在将代码编译为 C++;
  • 您正在使用 古老的 K&R C 编译器;

与 C 不同,C++ 不允许直接将 void * 赋值给其他指针类型。

此外,在 C89 标准之前,malloc 返回 char *,因此需要强制转换才能将结果分配给任何其他指针类型。

否则,通常首选 而不是 转换结果 - 这可能会导致维护问题。写成

会更简洁一些
studentInfo = malloc( sizeof *studentInfo * j * k );

由于studentInfo的类型是int *,表达式*studentInfo的类型是int,所以sizeof *studentInfo的结果是一样的作为 sizeof (int).

请记住 sizeof 是一个 运算符 ,而不是函数 - 只有当操作数是类型名称时才需要括号。