I'm trying to understand when I need to use malloc when using multiple levels of pointers. For example,
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
typedef struct {
char first[10];
char last[10];
} Person;
Person *p;
p = malloc(sizeof(Person));
strcpy(p->first, "John");
strcpy(p->last, "Doe");
printf("First: %s Last:%s\n", p->first, p->last);
return 0;
}
In this first version I'm using Person *p
and I only use malloc
to allocation space for type Person
. In the 2nd version, I'll change Person *p
to Person **p
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
typedef struct {
char first[10];
char last[10];
} Person;
Person **p;
*p = malloc(sizeof(Person));
strcpy((*p)->first, "John");
strcpy((*p)->last, "Doe");
printf("First: %s Last:%s\n", (*p)->first, (*p)->last);
return 0;
}
I'm still using only one malloc
even though there is now another pointer.
In this third version, I'll use Person ***p
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
typedef struct {
char first[10];
char last[10];
} Person;
Person ***p;
*p = malloc(sizeof(void));
**p = malloc(sizeof(Person));
strcpy((**p)->first, "John");
strcpy((**p)->last, "Doe");
printf("First: %s Last:%s\n", (**p)->first, (**p)->last);
return 0;
}
My questions:
1) Why do I need to malloc
space for **p
in the 3rd version, but I don't need to malloc
space for *p
? They are both pointers to pointers?
2) Also, why don't I need to malloc
space for p
in either the 2nd or 3rd version?
3) In the third version, what is the right size to malloc
for *p
? On my 64 bit Mac the sizeof(void)
is 1, and the sizeof(void*)
is 8, and both seem to work but what is the right one?
Dereferencing a pointer (*p
) which had not been initialised provokes undefined behaviour in any case.
When allocating space to a pointer you mostly ever want to allocate to it memory with the size of what is it pointing to by typically using the sizeof
operator. This latter case is the one and only exception to 1. that allows coding *p
.
So the 3rd example could look like this
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char first[10];
char last[10];
} Person;
int main(void) {
Person ***p;
p = malloc(sizeof *p);
*p = malloc(sizeof **p);
**p = malloc(sizeof ***p);
strcpy((**p)->first, "John");
strcpy((**p)->last, "Doe");
printf("First: %s Last:%s\n", (**p)->first, (**p)->last);
free(**p);
free(*p);
free(p);
return 0;
}