-2

What is the difference between this 3 ? are basically the same ?

 struct X* x = (struct X*)malloc(sizeof(struct X));
 
    struct X* x = (struct X*)malloc(sizeof(x)); 
       
    struct X* x = (struct X*)malloc(sizeof *x);

1 Answers1

5

They are not the same:

  1. sizeof(struct X) allocates space using the struct X definition.
  2. sizeof(x) allocates space based on the size of x. x is a pointer to struct X, and pointers will most likely be 4 or 8 bytes depending on your system.
  3. sizeof *x allocates space based on the size of *x, whose type is an object of struct X. Therefore, this allocates the same amount of space as 1.^

2 is incorrect. When allocating memory, you want to allocate space for "one level up". In this case, x is a struct X* type, so you must allocate enough space for a struct X object. 1 and 3 both do this. Of these, 3 is generally considered the preferred practice because it requires less maintenance. Consider later down the road, you decide to use a new structure here, struct myNewStruct* x. For 1, you would also have to change the amount of requested memory to malloc(sizeof(myNewStruct)). If using 3, you have no extra work to do, because now *x is a struct myNewStruct type, feeding the correct size to malloc "automatically". Also note that for similar reasons, casting the return result of malloc is bad practice, as you would also need to change your cast from (struct X*) to (struct myNewStruct*).

// This will compile and work, but see how many things have to change
// if your struct type ever changes? Three changes are required
struct myNewStruct* x = (struct myNewStruct*)malloc(sizeof(struct myNewStruct));

// as opposed to this, where only one change is needed
struct myNewStruct* x = malloc(sizeof *x);

^It's important to note that sizeof is almost always evaluated at compile time (only exception being VLAs I think), and the size of the type of the operand is what's evaluated.

yano
  • 4,827
  • 2
  • 23
  • 35
  • 1
    As a note for understanding the C standard and technical specifications in general: `sizeof *x` **cannot** allocate space based on the object `x` points to, because `x` does not point anywhere at this point in the code—it does not have a value. Suppose we wrote `x = NULL; printf("%zu\n", sizeof *x);`. Here there is definitely no object that `x` points to, yet `sizeof` gives us the size we expect. The way this is written in the C standard is that `sizeof` determines the size from the **type** of the operand. The type of the expression `*x` is `struct X`, regardless of whether `x` has a value. – Eric Postpischil Jul 21 '21 at 20:25
  • @EricPostpischil very important clarification, I will work that into the answer. – yano Jul 21 '21 at 20:30