简体   繁体   English

了解动态 memory 分配

[英]Understanding dynamic memory allocation

I am a beginner in C programming.我是 C 编程的初学者。 I was recently taught how to use malloc , but I don't think that I quite understand it.最近有人教我如何使用malloc ,但我认为我不太了解它。 Like why does it need a void * or any typecast as a matter of fact?就像事实上为什么它需要一个void *或任何类型转换? Why does the syntax itself have (void *) in void *malloc(size_t size) .为什么语法本身在void *malloc(size_t size)中有(void *) ) 。 And how does the variable assigned the malloc function know where the memory block begins from?分配给malloc function 的变量如何知道 memory 块从哪里开始? Does the malloc function return an address or something after it has assigned a memory block? malloc function 在分配 memory 块后是否返回地址或其他内容?

In the class our prof gave us this program.在 class 我们的教授给了我们这个程序。 I understand how 2d memory allocation works too.我也了解 2d memory 分配的工作原理。

#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();
}

In this we are assigning the studentInfo pointer the malloc function right?在此我们为studentInfo指针分配 malloc function 对吗? So... how does studentInfo know that the address of the memory block is USA and not Antarctica??那么... studentInfo怎么知道 memory 块的地址是美国而不是南极洲? And I know that it is not a good practise to typecast malloc with some other datatype.而且我知道用其他数据类型对 malloc 进行类型转换不是一个好习惯。 But why (int *) .但是为什么(int *) Why does malloc need a pointer??为什么 malloc 需要指针?? If malloc needs a pointer that means that it is returning an address right?如果 malloc 需要一个指针,这意味着它正在返回一个地址,对吗? I asked this to my friend and he said no malloc doesn't return anything.我问我的朋友这个问题,他说没有 malloc 不会返回任何东西。 And one more thing is it necessary that we need the typecast to be in brackets?还有一件事是我们需要将类型转换放在括号中吗?

Please explain in very simple terms.请用非常简单的术语解释。 Thank you.谢谢你。

Why does the syntax itself have (void *) in void *malloc(size_t size).为什么语法本身在 void *malloc(size_t size) 中有 (void *)。

Because malloc is a function and functions have a return type.因为malloc是 function 并且函数具有返回类型。 This tells that this function returns this particular type.这表明此 function 返回此特定类型。 So (void *) means malloc return a void * .所以(void *)意味着malloc返回一个void *

Does the malloc function return an address or something after it has assigned a memory block? malloc function 在分配 memory 块后是否返回地址或其他内容?

Malloc allocates the memory of the size specified into the heap and returns a pointer to that allocated memory. Malloc 将指定大小的 memory 分配到堆中,并返回指向已分配 memory 的指针。

In this we are assigning the studentInfo pointer the malloc function right?在此我们为 studentInfo 指针分配 malloc function 对吗? So... how does studentInfo know that the address of the memory block is USA and not Antarctica??那么... studentInfo 怎么知道 memory 块的地址是美国而不是南极洲?

Not exactly.不完全是。 studentInfo is not assigned the malloc function but studentInfo points to the pointer returned by malloc . studentInfo未分配malloc function 但studentInfo指向malloc返回的指针。 This was studentInfo now points to the allocated memory.这是studentInfo现在指向分配的 memory。

Why does malloc need a pointer??为什么 malloc 需要指针??

malloc doesn't need a pointer. malloc不需要指针。 It takes the amount of memory you want to allocate as an argument.它将您要分配的 memory 的数量作为参数。

You don't need to typecast here, as void * is automatically promoted.您不需要在这里进行类型转换,因为void *会自动提升。

And one more thing is it necessary that we need the typecast to be in brackets?还有一件事是我们需要将类型转换放在括号中吗?

Yes, that's the syntax for typecasting.是的,这就是类型转换的语法。 Without brackets, it will result in compilation errors.没有括号会导致编译错误。

malloc returns void* because malloc allocates not only int , it can allocate floats, doubles even structures etc. Reason of returning pointer is because it can allocate so much memory in heap, heap is larger than stack and if allocated memory is so big for stack you will receive an error(probably stackoverflow) + copy memory is meaningless if we just can copy its address and refer it by pointer. malloc returns void* because malloc allocates not only int , it can allocate floats, doubles even structures etc. Reason of returning pointer is because it can allocate so much memory in heap, heap is larger than stack and if allocated memory is so big for stack你会收到一个错误(可能是stackoverflow)+复制memory如果我们可以复制它的地址并通过指针引用它是没有意义的。 And void * is a special kind that everything can be assigned no matter what type of address it is.void *是一种特殊的类型,无论它是什么类型的地址,都可以分配。 Yes you need to cast it, if you don't then compiler will give you an error是的,你需要转换它,如果你不这样做,那么编译器会给你一个错误

The malloc function call allocates a block of memory large enough to hold j*k int objects and returns the address of the first element of that block - that address value is assigned to studentInfo , giving us something like this: malloc function 调用分配一块studentInfo大到足以容纳j*k int对象并返回该块的第一个元素的地址,给我们分配了这样的地址值:

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

Thus, studentInfo points to (stores the address of) the first int object in that sequence.因此, studentInfo指向(存储地址)该序列中的第一个int object。

The (int *) preceding the malloc call in your code is a cast - it means "treat the result of the following expression (the value returned by malloc ) as an int * , or pointer to int ."代码中malloc调用之前的(int *)是一个强制转换- 这意味着“将以下表达式的结果(由malloc返回的值)视为int *或指向int的指针。”

There only two circumstances where you must cast the result of malloc :只有两种情况必须malloc的结果:

  • you're compiling the code as C++;您正在将代码编译为 C++;
  • you're using an ancient K&R C compiler;您正在使用古老的 K&R C 编译器;

Unlike C, C++ does not allow direct assignment of void * to other pointer types.与 C 不同,C++ 不允许将void *直接分配给其他指针类型。

Also, prior to the C89 standard, malloc returned char * , so a cast was required to assign the result to any other pointer type.此外,在 C89 标准之前, malloc返回char * ,因此需要进行强制转换才能将结果分配给任何其他指针类型。

Otherwise, it's generally preferred to not cast the result - it can lead to maintenance headaches down the line.否则,通常最好不要投射结果 - 这可能会导致维护问题。 It would be a bit cleaner to write it as写成这样会更干净一些

studentInfo = malloc( sizeof *studentInfo * j * k );

Since the type of studentInfo is int * , the type of the expression *studentInfo is int , so the result of sizeof *studentInfo is the same as sizeof (int) .由于studentInfo的类型是int * ,所以表达式*studentInfo的类型是int ,所以sizeof *studentInfo的结果与sizeof (int)相同。

Remember that sizeof is an operator , not a function - parens are only required if the operand is a type name.请记住, sizeof是一个运算符,而不是 function - 仅当操作数是类型名称时才需要括号。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM