Чтение деклараций указателей справа налево помогает понять их.
Первый - это указатель на символ, который является константой. Вы не можете изменить символ, на который он указывает, потому что char является константой.
Второй является указателем const на символ. Вы не можете изменить значение указателя (местоположение символа, на которое он указывает), поскольку указатель является константой.
Следить typedef char* pstring
(и это хорошая идея, чтобы переместить звездочку от вашего TypeName, поскольку это не является его частью), то константность применяется к типу, который он создает, как это делает все остальное:
int i;
const int i = 0; // actually int const i = 0
char* p;
const char* p = 0; // actually char const* p = 0
typedef char* pstring;
const pstring ps = 0; // actually 'pstring const' -> 'char* const' ps = 0
Именно по этой причине, некоторые стандарты кодирования (например, Мишр) требуют, чтобы вы разместить отборочные резюме после имени типа, потому что он работает лучше, чтобы показать, что сопзЬ-ность квалифицирует тип, это зависит от него - а не наоборот.
Pstring является указателем на char, поэтому const pstring является указателем const на символ. – immibis