-2

I am a beginner in C programming. I was recently taught how to use malloc, but I don't think that I quite understand it. Like why does it need a void * or any typecast as a matter of fact? Why does the syntax itself have (void *) in void *malloc(size_t size). And how does the variable assigned the malloc function know where the memory block begins from? Does the malloc function return an address or something after it has assigned a memory block?

In the class our prof gave us this program. I understand how 2d memory allocation works too.

#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? So... how does studentInfo know that the address of the memory block is USA and not Antarctica?? And I know that it is not a good practise to typecast malloc with some other datatype. But why (int *). Why does malloc need a pointer?? If malloc needs a pointer that means that it is returning an address right? I asked this to my friend and he said no malloc doesn't return anything. And one more thing is it necessary that we need the typecast to be in brackets?

Please explain in very simple terms. Thank you.

  • I actually think the cast is redundant and unnecessary unless you have to use `malloc` with C++ for some reason. https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc – mediocrevegetable1 Mar 21 '21 at 06:52
  • *how does studentInfo know that the address of the memory block is USA and not Antarctica*. Not sure what you mean by that. `malloc` returns the address of the allocated memory. It doesn't put anything in there. You are the one who writes data into the memory block so you should know what each block will contain. – kaylum Mar 21 '21 at 06:53
  • *If malloc needs a pointer that means that it is returning an address right?*. There's no need to debate with anyone. Just read the [man page](https://www.man7.org/linux/man-pages/man3/malloc.3.html). It tells you exactly what is returned: *The malloc() and calloc() functions return a pointer to the allocated memory* – kaylum Mar 21 '21 at 06:54
  • _"Why does malloc need a pointer?? If malloc needs a pointer that means that it is returning an address right?"_ Yes, it returns an address. Without getting an address into a pointer, the allocated memory would be lost, and you would have a memory leak. – mediocrevegetable1 Mar 21 '21 at 06:55
  • @kaylum That was my way of saying that the address of the memory block is not A but B. – somepersonidk Mar 21 '21 at 06:56
  • @kaylum I usually avoid manual pages because they are very beginner friendly. But thank you the page you sent seems simple enough. – somepersonidk Mar 21 '21 at 06:58
  • @SuburbanBourbon `malloc` will never return memory that has already been allocated (at least I think that's what you're asking), or that would cause a serious issue. It will return uninitialized allocated memory that hasn't been touched. – mediocrevegetable1 Mar 21 '21 at 06:58
  • @mediocrevegetable1 Thank you. I knew it that it would return a address. – somepersonidk Mar 21 '21 at 06:59
  • @mediocrevegetable1 No no I meant to ask if it returns an address or not. And what does "return memory" even mean? – somepersonidk Mar 21 '21 at 07:00
  • @SuburbanBourbon `malloc` will always return an address to allocated memory unless it fails for some reason, in which case it will return a `NULL` pointer. It's unlikely that it will fail (and I think with the OOM killer it may just fail anyway), but it is always good to check. – mediocrevegetable1 Mar 21 '21 at 07:03

3 Answers3

0

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

Because malloc is a function and functions have a return type. This tells that this function returns this particular type. So (void *) means malloc return a void *.

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

Malloc allocates the memory of the size specified into the heap and returns a pointer to that allocated memory.

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??

Not exactly. studentInfo is not assigned the malloc function but studentInfo points to the pointer returned by malloc. This was studentInfo now points to the allocated memory.

Why does malloc need a pointer??

malloc doesn't need a pointer. It takes the amount of memory you want to allocate as an argument.

You don't need to typecast here, as void * is automatically promoted.

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.

ameyCU
  • 16,489
  • 2
  • 26
  • 41
  • _Not exactly. studentInfo is not assigned the malloc function but studentInfo points to the pointer returned by malloc. This was studentInfo now points to the allocated memory._ So, this means that it is doing something like a double pointer right? – somepersonidk Mar 21 '21 at 07:02
  • @SuburbanBourbon Double pointer would be different. It will just point to the pointer returned by the `malloc`. So now, `studentInfo` points to same memory as the pointer returned by `malloc` did. – ameyCU Mar 21 '21 at 07:10
  • Okay okay I think I understand it now. Thanks – somepersonidk Mar 21 '21 at 07:17
0

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. And void * is a special kind that everything can be assigned no matter what type of address it is. Yes you need to cast it, if you don't then compiler will give you an error

Kanony
  • 509
  • 2
  • 12
0

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:

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

Thus, studentInfo points to (stores the address of) the first int object in that sequence.

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."

There only two circumstances where you must cast the result of malloc:

  • you’re compiling the code as C++;
  • you’re using an ancient K&R C compiler;

Unlike C, C++ does not allow direct assignment of void * to other pointer types.

Also, prior to the C89 standard, malloc returned char *, so a cast was required to assign the result to any other pointer type.

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).

Remember that sizeof is an operator, not a function - parens are only required if the operand is a type name.

John Bode
  • 119,563
  • 19
  • 122
  • 198
  • _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). Remember that sizeof is an operator, not a function - parens are only required if the operand is a type name._ Didn't know about this thank you. – somepersonidk Mar 22 '21 at 11:15