Ответ 1
В первом примере (char *hi = "hello";
) вы создаете неконстантный указатель, который инициализируется, чтобы указать на статическую константную строку "привет". Этот указатель мог бы теоретически указать на что угодно.
Во втором примере (char hi[] = "hello";
) вы конкретно определяете массив, а не указатель, поэтому адрес, который он ссылается, не модифицируется. Обратите внимание, что массив можно рассматривать как немодифицируемый указатель на определенный блок памяти.
Ваш первый пример фактически компилируется без проблем в С++ (мой компилятор, по крайней мере).