【问题标题】:Understanding dynamic memory allocation了解动态内存分配
【发布时间】:2021-06-18 02:58:18
【问题描述】:

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

在课堂上,我们的教授给了我们这个程序。我也了解 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 怎么知道内存块的地址是美国而不是南极洲?而且我知道用其他数据类型对 malloc 进行类型转换不是一个好习惯。但是为什么(int *)。为什么 malloc 需要一个指针?如果 malloc 需要一个指针,这意味着它正在返回一个地址,对吗?我向我的朋友问过这个问题,他说没有 malloc 不会返回任何东西。还有一件事是我们需要将类型转换放在括号中吗?

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

【问题讨论】:

  • 我实际上认为强制转换是多余且不必要的,除非您出于某种原因必须在 C++ 中使用 mallocstackoverflow.com/questions/605845/…
  • studentInfo怎么知道内存块的地址是美国而不是南极洲。不知道你的意思是什么。 malloc 返回分配内存的地址。它没有在里面放任何东西。您是将数据写入内存块的人,因此您应该知道每个块将包含什么。
  • 如果 malloc 需要一个指针,这意味着它正在返回一个地址,对吗?。没有必要和任何人争论。只需阅读man page。它准确地告诉你返回了什么:malloc() 和 calloc() 函数返回一个指向分配内存的指针
  • “为什么 malloc 需要一个指针??如果 malloc 需要一个指针,这意味着它正在返回一个地址对吗?” 是的,它返回一个地址。如果没有将地址放入指针中,分配的内存将会丢失,并且会发生内存泄漏。
  • @kaylum 这就是我的说法,内存块的地址不是A而是B。

标签: c pointers multidimensional-array malloc dynamic-memory-allocation


【解决方案1】:

为什么语法本身在void *malloc(size_t size)中有(void *)。

因为malloc 是一个函数,而函数有一个返回类型。这告诉这个函数返回这个特定的类型。所以(void *) 意味着malloc 返回一个void *

malloc函数在分配内存块后是否返回地址或其他内容?

Malloc 将指定大小的内存分配到堆中,并返回一个指向该分配内存的指针。

在这里我们为 studentInfo 指针分配 malloc 函数对吗?那么……studentInfo怎么知道内存块的地址是美国而不是南极呢??

不完全是。 studentInfo 没有分配malloc 函数,但studentInfo 指向malloc 返回的指针。这是studentInfo 现在指向分配的内存。

为什么 malloc 需要一个指针??

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

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

还有一件事是我们需要将类型转换放在括号中吗?

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

【讨论】:

  • 不完全是。 studentInfo 没有分配 malloc 函数,但 studentInfo 指向 malloc 返回的指针。这是 studentInfo 现在指向分配的内存。 那么,这意味着它正在执行类似双指针的操作吗?
  • @SuburbanBourbon 双指针会有所不同。它只会指向malloc 返回的指针。所以现在,studentInfo 指向与 malloc 返回的指针相同的内存。
  • 好吧好吧我想我现在明白了。谢谢
【解决方案2】:

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

【讨论】:

  • 非常感谢您的解释。这就是我一直在寻找的
【解决方案3】:

malloc 函数调用分配了一个足够大的内存块以容纳 j*k int 对象并返回该块的第一个元素的地址 - 该地址值被分配给 studentInfo,给了我们一些东西像这样:

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

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

代码中malloc 调用之前的(int *) 是一个cast - 这意味着“将以下表达式的结果(malloc 返回的值)视为@987654331 @,或指向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 是一个运算符,而不是一个函数 - 仅当操作数是类型名称时才需要括号。

【讨论】:

  • 由于studentInfo的类型是int *,所以表达式*studentInfo的类型是int,所以sizeof *studentInfo的结果和sizeof(int)是一样的。请记住 sizeof 是一个运算符,而不是一个函数 - 只有当操作数是类型名称时才需要括号。不知道这个谢谢。
猜你喜欢
  • 2018-08-05
  • 2019-07-08
  • 2017-05-07
  • 1970-01-01
  • 2011-09-16
  • 1970-01-01
  • 2021-02-15
  • 2013-07-01
相关资源
最近更新 更多