This code is invalid C++ and in most cases won't even compile.
You were probably interested in this article:
What is the difference between const int*, const int * const, and int const *?
All three declarations
const int const* p2 = &i;
const int * p2 = &i;
int const* p2 = &i;
are just different ways to write the same thing: a (non-const pointer) to (const int). Most compilers will balk when it's declared like in your code through, because it's not a standard C++ and a likely error.
You will be able to write
p2 = p3; // assign value of (pointer p3) to (pointer p2)
because (pointer) is not const, but not
*p2 = *p3; // assign (object) pointed by (pointer p3) to (object) pointed by (pointer p2)
because (object) that is pointed by a pointer is const (const int in this case)
But if you will write
int * const p2 = &i;
then it'll be a (const pointer) pointing to (int) object. Then things will be completely opposite:
p2 = p3; // don't work
*p2 = *p3; // work!
You can also write const int * const to prohibit both options or don't use const to allow both.
Constexpr is a very different keyword. Rather than say that it's simply a (const object), it says that it's a (const object with value known at compile time). Most "const objects" in C++ are not 'constants' in mathematical sense since they could be different in different runs of same program. They are created at runtime and we just tell compiler that we're not going to change them later. On the other hands, 'constexpr' means that it's a 'real' constant that is defined once and for all. It's always the same and thereby it gets hardcoded in compiled binary code. Since you are beginner, think about it as a fancy C++ version of #define. In your case you tried to declare a pointer to const int to be constexpr, but it won't happen since this pointer is going to be different in different runs of your program and cannot be determined at compile time.