this show how to point and check addresses of pointer on the stack
#include <stdio.h>
int main(){
    double X = 2.25;
    double* pX = &X;
    double** ppX = &pX;
    printf("Addr X:   %8X\n", &X);
    printf("Addr pX:  %8X\n", &pX);
    printf("Addr ppX: %8X\n", &ppX);
    printf("Val X: %f", **ppX);
}
and this show how to point and show addresses on the heap
#include <stdio.h>
#include <stdlib.h>
int main(){
    double X = 2.25;
    double** pX = (double**) malloc(sizeof(double**));
    double*** ppX = (double***) malloc(sizeof(double***));
    *pX = &X;
    *ppX = &*pX;
    printf("Addr X:   %8X\n", &X);
    printf("Addr pX:  %8X\n", &*pX);
    printf("Addr ppX: %8X\n", &*ppX);
    printf("Val X: %f", ***ppX);
}
you will get a space from heap and store address in them so you need pointer to pointer just for save address of 'X'
Edit 1:
for better answer to comment i put code here
below code show use & operator
'&' operator just get address of variable, so *& get value of address that variable
now look at below code bot set value of x and both correct
#include <stdio.h>
int main(){
    int X;
    *&X = 10;
    printf("X: %d\n", X);
    X = 20;
    printf("X: %d\n", X);
}