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 **ptrandsizeof *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 **ptrresults 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.
