1

I always confuse about what to put inside of sizeof when malloc

for example,

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

or

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

or, char ***p = malloc(sizeof(WHAT_SHOULD_I_PUT_HERE));???

someday, some c guru told me that use the variable like this:

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

So i wrote some code:

void main() {
  int n = 1000000, i;
  char **p = malloc(sizeof(char *) * n);    // works
  //char **p = malloc(sizeof(**p) * n);     // not work, segfault
  for(i=0; i<n; i++) {
          // p[i] = malloc(sizeof(char));   // works
          // p[i] = malloc(sizeof(p[i]));   // works
          // p[i] = malloc(sizeof(*p[i]));  // works
  }
  for(i=0; i<n; i++) {
          free(p[i]);
  }
  free(p);
}

still get confused, any easy way to remember?

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
Sato
  • 8,192
  • 17
  • 60
  • 115
  • 4
    In the cases you show, use `sizeof *p`. `sizeof **p` in your example fails because you should only do *one* dereference (to get the type that `p` points to). – Some programmer dude Sep 15 '17 at 08:38
  • 1
    related: https://stackoverflow.com/questions/17258647/why-is-it-safer-to-use-sizeofpointer-in-malloc – Jens Gustedt Sep 15 '17 at 08:42
  • BTW: it is not a parameter, since `sizeof` is not a function. It is a unary operator, so in `sizeof *p` , *p is its operand. And BTW2 `main()` should return int. – joop Sep 15 '17 at 08:48
  • 2
    I'd note that the dup question's not accepted answer with far fewer upvotes fits better than the accepted one. – Armali Sep 15 '17 at 09:18
  • 1
    @Sato-- `malloc()` returns a pointer to something. You need to provide the size of that something (or a multiple of that size). With `struct sth *p = malloc(sizeof *p);` the operand to the `sizeof ` operator is the _type_ of the expression `*p`. Now, `p` is a pointer to `struct sth`, so `*p` has type `struct sth`. It works like this always, for any type. `struct sth *****p = malloc(sizeof *p);`: here `p` is a pointer to `(struct sth ****)`, so `*p` has type `(struct sth ****)`. You always need one dereference in the `sizeof` expression when using this idiom. – ad absurdum Sep 15 '17 at 09:20
  • 1
    @Armali : yes, the accepted answer is rather poor. – joop Sep 15 '17 at 10:26

3 Answers3

4

sizeof(struct sth) is the size your struct takes in memory.

sizeof(struct sth*) is the size of a pointer to struct sth (usually 4 or 8 bytes); actually it's the size of any pointer on your platform.

So you need:

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

But it is better to write:

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

sizeof(*p); being the size of the object p points to and as p points to struct sth, sizeof(*p) is the same thing as sizeof(struct sth).

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
Jabberwocky
  • 48,281
  • 17
  • 65
  • 115
  • what about : `struct sth **p1 = malloc(sizeof(??? )); struct sth ***p2 = malloc(sizeof(??));` – Sato Sep 15 '17 at 08:46
  • @Sato `struct sth **p1 = malloc(sizeof(**p));`. In this case you want to allocate a pointer to a pointer. But allocating just one pointer to a pointer is usually not very useful. Most of the time you would allocate space for more than one pointer to pointer, e.g: `struct sth **p1 = malloc(sizeof(**p) * nb_of_pointers);` – Jabberwocky Sep 15 '17 at 08:57
  • but `char **p = malloc(sizeof(**p) * n);` // not work, segfault – Sato Sep 15 '17 at 09:00
  • If it segfaults, you need to post more code and tell us what you are _actually_ trying to do. You should probably post A new specific question including a [MCVE] – Jabberwocky Sep 15 '17 at 09:01
  • 2
    @MichaelWalz - your comment is incorrect. `struct sth **p1 = malloc(sizeof(*p1))` is still correct. The difference is that it would also be necessary to follow that up with `*p1 = malloc(sizeof(**p1))` if double dereferencing `p1` (e.g. `**p1 = some_sth` or `(*p1)->member = something` is required. – Peter Sep 15 '17 at 11:21
1

When you write sizeof, the C compiler computes the actual size of what you gave it. When you type sizeof (*int) for instance, you ask the compiler to compute the size of a ... pointer ! That is 4 or 8 bytes (32, 64 bits respectively) depending on your machine architecture.

However, if you type sizeof (struct foo) it will return the amount of bytes a struct of type foo would occupy in memory.

At some point you need to create enough memory for a struct and its values. So generally you want to pass sizeof (struct foo) to malloc.

TDk
  • 1,019
  • 6
  • 18
1

If you want to use the *p rule then in the case below you need to do

char **p = malloc(sizeof(*p) * n);

Even if you have char ***p you would still use

char ***p = malloc(sizeof(*p) * n);    
Rishikesh Raje
  • 8,556
  • 2
  • 16
  • 31