1

On C programming language, I have encountered several ways to allocate memory for a data structure:

#include <stdio.h>
#include <stdlib.h>

typedef struct Element
{
    int number;
    struct Element *next;
}Element;

int main(int argc, char *argv[])
{
    /* Method NO.1 */
    Element *ptr1 = malloc(sizeof(*ptr1));
    /* Method NO.2 */
    Element *ptr2 = malloc(sizeof(Element));
    /* Method NO.3 */
    Element *ptr3 = (Element*) malloc (sizeof(Element));

    return EXIT_SUCCESS;
}

There are no compilation errors.
But I got confused, so what is the difference beteween them, and which one should be preferred?

cheater
  • 93
  • 1
  • 6

3 Answers3

2
  1. The best way by, in my opinion, a country mile. Remember that sizeof *ptr1 is compile-time evaluable so there's no chance of a run-time crash due to dereferencing an uninitialised pointer.

  2. Not my favourite way - despite it arguably being the most readable - since you might change the type of *ptr2 and forget to adjust sizeof Element. And those kind of bugs are a nightmare to track down.

  3. Is horrible: the cast is unnecessary in C and is even occasionally harmful. See Do I cast the result of malloc?.

Community
  • 1
  • 1
Bathsheba
  • 231,907
  • 34
  • 361
  • 483
  • For the second method, you said we might change the type of `*ptr2` and forget to adjust `sizeof Element`, could you give me an example? – cheater Aug 22 '16 at 15:06
  • Sure, you invent a new structure called `ElementEx` (which is larger than `Element`), and retain `ElementEx *ptr2 = malloc(sizeof(Element));` Eventually your computer will melt. – Bathsheba Aug 22 '16 at 15:08
  • Yeah, You are right, with the first method, we can always allocate the exact memory needed for the structure. So I will prefer the first method as you. – cheater Aug 22 '16 at 15:14
1
#1

Element *ptr1 = malloc(sizeof(ptr1)); is wrong, you want to allocate space with the size of an Element, not with the size of a pointer to that Element,

Change to

Element *ptr1 = malloc(sizeof(*ptr1));

#2

Element *ptr2 = malloc(sizeof(Element));

You are using the typedef (an alias of struct Element), that's fine.


#3

Element *ptr3 = (Element*) malloc (sizeof(Element));

Take a look to Do I cast the result of malloc?


You can also use:

Element *ptr4 = malloc(sizeof(struct Element));

even if struct Element is typedefed.

Community
  • 1
  • 1
David Ranieri
  • 39,972
  • 7
  • 52
  • 94
1

The first method is the preferred way of doing this. It allocates space for sizeof(*ptr1) bytes, where *ptr1 is the structure in question. If for some reason the type of this variable is modified, the above allocation will still work.

The second method is correct because it allocates space for sizeof(Element) bytes, which is the size of the structure. It is not preferred however, because if the type of ptr1 is changed for some reason but the expression above is not, you won't be allocating the proper amount of space.

The third method is not correct because you should not cast the return value of malloc.

Community
  • 1
  • 1
dbush
  • 205,898
  • 23
  • 218
  • 273