char [] str1 = "foo" выделяет массив символов в стеке (при условии, что это внутри функции). Этот массив может быть изменен без проблем.
const char * str = "foo" дает вам указатель на строку foo, которая обычно находится в постоянной памяти.
char * str = "foo" сделает то же самое, но неявно удалит const (без фактического изменения факта, что указатель, скорее всего, указывает на постоянную память).