54

Given

struct node
{
     int a;
     struct node * next;
};

To malloc a new structure,

struct node *p = malloc(sizeof(*p));

is safer than

struct node *p = malloc(sizeof(struct node));

Why? I thought they are the same.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
  • 8
    FYI, when used with a variable, `sizeof` doesn't need parens: `p = malloc(sizeof*p);` – luser droog Jun 23 '13 at 07:46
  • 64
    It's more readable with parens – Tomer Arazy Jun 23 '13 at 07:48
  • 7
    @TomerArazy: I beg to differ; it is _less_ readable with parens. Without parens, it _cannot_ be a typename; the lack of parens helps the human reader to disambiguate. (minor issue: also, the parens could suggest that sizeof is a function, which it is not) – wildplasser Jun 23 '13 at 09:18
  • 15
    It is more readable without parentheses but with a space: `sizeof *p`. – Eric Postpischil Jun 23 '13 at 11:47
  • 10
    It is not more readable with parens, or without parens. These are opinions, not facts. But it is fact that the parens aren't necessary because sizeof applies as a unary operator to an expression. If you don't always use parentheses with every unary operators, why always use them with sizeof. – Kaz Jun 23 '13 at 15:27
  • 3
    Also, parentheses do not help resolve any ambiguity because unless you don't know the first thing about C, you know that `sizeof *p` cannot possibly be `(sizeof *) p`, and you know that it isn't a `sizeof` variable being multiplied by `p`. – Kaz Jun 23 '13 at 15:31

3 Answers3

77

It is safer because you don't have to mention the type name twice and don't have to build the proper spelling for the "dereferenced" version of the type. For example, you don't have to "count the stars" in

int *****p = malloc(100 * sizeof *p);

Compare that to the type-based sizeof in

int *****p = malloc(100 * sizeof(int ****));

where you have to make sure you used the right number of * under sizeof.

In order to switch to another type you only have to change one place (the declaration of p) instead of two. And people who have the habit of casting the result of malloc have to change three places.

More generally, it makes a lot of sense to stick to the following guideline: type names belong in declarations and nowhere else. The actual statements should be type-independent. They should avoid mentioning any type names or using any other type-specific features as much as possible.

The latter means: Avoid unnecessary casts. Avoid unnecessary type-specific constant syntax (like 0.0 or 0L where a plain 0 would suffice). Avoid mentioning type names under sizeof. And so on.

mitchnegus
  • 85
  • 5
AnT stands with Russia
  • 312,472
  • 42
  • 525
  • 765
  • 13
    It is worth nothing that the fact that, when the type is changed, changing it in the declaration of p is sufficient (there is no need to change it in the `malloc`) not only means there is less work but that there is less chance of error. Thus, this helps reduces bugs. – Eric Postpischil Jun 23 '13 at 11:49
  • AndreyT, I see your point, abstractly speaking... but I'll bet you a beer there's never been a platform in the history of computers where sizeof(int ****) != sizeof(int ***) :) – Josh Dec 19 '14 at 23:41
  • 2
    @Josh: You are basically saying that every time you need to know the pointer size, you can just use `sizeof(double *)`. Yes, it will work, but things like that should produce the same kind of unresolved tension as an unmatched left parenthesis (http://xkcd.com/859/) – AnT stands with Russia Dec 19 '14 at 23:50
22

Because if at some later point in time p is made to point to another structure type then your memory allocation statement using malloc doesn't have to change, it still allocates enough memory required for the new type. It ensures:

  • You don't have to modify the memory allocation statement every time you change the type it allocates memory for.
  • Your code is more robust and less prone to manual errors.

In general it is always a good practice to not rely on concrete types and the the first form just does that ,it doesn't hard code a type.

Alok Save
  • 202,538
  • 53
  • 430
  • 533
7

It is convenient, because you can convert this:

struct node *p= malloc(sizeof(*p));

Into this:

#define MALLOC(ptr)   (ptr) = malloc(sizeof(*(ptr) ))

struct node *p;
MALLOC(p);

Or, for an array:

#define MALLOC_ARR(ptr, arrsize) \
       (ptr) = malloc(sizeof(*(ptr) ) * arrsize)

struct node *p;
MALLOC_ARR(p, 20);

And why is this safe? Because the user who uses these macros would be less likely to make mistakes which were outlined by AndreyT, just as in the case of DIM() to get the size of a static array.

#define DIM(arr)   ((sizeof(arr))/(sizeof(arr[0])))

This is also safer, because the user does not need to make the static array size consistent in several places. Set the array size in one place and then just use the DIM() and you're done! The compiler takes care of it for you.

slashmais
  • 7,069
  • 9
  • 54
  • 80
ruben2020
  • 1,549
  • 14
  • 24