The purpose of a pointer is to save the address of a specific variable. Then the memory structure of following code should look like:
int a = 5;
int *b = &a;
If the purpose of pointer is just to save the memory address, I think there should be no hierarchy if the address we are going to save refers variable, pointer, double pointer, ... etc
At runtime, yes, a pointer just holds an address. But at compile time there is also a type associated with every variable. As the others have said, int* and int** are two different, incompatible types.
There is one type, void*, that does what you want: It stores only an address, you can assign any address to it:
int a = 5;
int *b = &a;
void *c = &b;
But when you want to dereference a void*, you need to supply the 'missing' type information yourself:
int a2 = **((int**)c);