Если переменную j и указатель p1 разместить внутри функции - то не работает( А если переменную j вынести, то работает. А с переменной i работает в любом случае.
Понял про что вы, ну когда обычная переменная объявляется в теле функции, она создается на стеке, в этом случае невозможно на этапе компиляции/линковки узнать её адрес. Когда же объявляется вне функции, переменная размещается в сегменте данных, в этом случае на этапе линковки адрес будет известен. А constexpr это выражение уровня компиляции, поэтому и не может узнать адрес переменной на стеке.
В дополнении еще один момент, выражения помеченные как const будут размещены в памяти только в случае если будет разыменование, иначе будет сразу подставлять значения.
Взятие указателя уже разыменование. Нет, если просто написать где либо
const int n = 5;
пока не будет взят адрес, данные в памяти размещаться не будут.