Home > database >  difference between sizeof *ptr and sizeof **ptr when allocating memory
difference between sizeof *ptr and sizeof **ptr when allocating memory

Time:11-08

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 and sizeof *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* and double* types, but when I'm dealing with chars*, using sizeof **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.

  • Related