In this piece of code:
void func(size_t dim, double **ptr){
(*ptr) = malloc(dim * sizeof **ptr);
/* Perform Calculations...*/
}
What is the difference between using sizeof **ptr
and sizeof *ptr
? This is confusing me. It seems to have no difference when I'm dealing with int*
and double*
types, but when I'm dealing with chars*
, using sizeof **ptr
results in a segmentation fault. Could you help me with that?
Thanks in advance!
CodePudding user response:
What is the difference between using
sizeof **ptr
andsizeof *ptr
?
sizeof *ptr
is the size of the type that ptr
points to.
sizeof **ptr
is the size of the type that is pointed to by what ptr
points to.
The declaration double **ptr
says ptr
is a pointer to a pointer to a double
. Then *ptr
is a pointer to a double
, so sizeof *ptr
is the size of a pointer to double
. And **ptr
is a double
, so sizeof **ptr
is the size of a double
.
It seems to have no difference when I'm dealing with
int*
anddouble*
types, but when I'm dealing withchars*
, usingsizeof **ptr
results in a segmentation fault.
If a pointer is four bytes in your system, an int
is four bytes, and a double
is eight bytes, then allocating enough space for an int
or double
also allocates enough space for a pointer. However, allocating space for a char
is not enough for a pointer.
This is actually unlikely to make a noticeable different for a single pointer, as malloc
commonly works in units of eight or 16 bytes, so asking it to allocate space for a char
would actually give enough for a pointer, notwithstanding compiler optimization. However, if you allocate dim * sizeof **ptr
bytes where ptr
has type char **
and dim
is large, then this will only allocate enough space for dim
char
elements and not enough space for dim
pointers.
CodePudding user response:
The parameter ptr
is declared like
double **ptr
That is the original pointer used as an argument is passed to the function by reference indirectly through a pointer to it.
Within the function you need to assign a value to the original pointer by means of dereferencing the parameter.
(*ptr) = malloc(dim * sizeof **ptr);
The original pointer *ptr
must be assigned with the address of a dynamically allocated array of doubles. So dereferencing the pointer in the expression
sizeof **ptr
you will get the size of an object of the type double
.
To make it more clear you could use for example an intermediate pointer like
double *tmp = malloc(dim * sizeof *tmp );
*ptr = tmp;
As for the type of the operand in the expression sizeof *ptr
then it has the type double *
and it produces the size of an object of the pointer type double *
instead of the required size of an object of the type double
.
CodePudding user response:
Pointers inside the sizeof() operator aren't evaluated, let's say you have this:
int * pointer = malloc(sizeof(* pointer));
What you're doing here is "malloc sizeof pointed type", advantage is you can change the type of the pointer without changing the sizeof() part.
Now, with a double pointer:
int ** pointer;
// allocate enough space to store a pointer: sizeof(* pointer) <--> sizeof(int *)
pointer = malloc(sizeof(* pointer));
And with this:
int ** pointer;
// allocate enough space to store an int: sizeof(** pointer) <--> sizeof(int)
pointer = malloc(sizeof(** pointer));
On a 64 bits system, first case would likely give you 8 bytes, and second case only 4 bytes, potentally crashing if you meant to use 8 bytes.
(*ptr) = malloc(dim * sizeof **ptr);
You're storing inside *ptr, which is of type double*, since ptr has type double**. You allocate n*sizeof(double) bytes, not n*sizeof(double*) bytes, might be different on your system.
Or maybe the crash happens when you access that memory.