БлогNot. Указатель на константу и константный указатель

Помощь дата->рейтинг Поиск Почта RSS канал Статистика nickolay.info Домой

Указатель на константу и константный указатель

Одна из частых проблем новичков при работе со строками Си (char *) обычно формулируется примерно следующим образом:

Почему так

char* kk = "345345";
kk[1] = 0x00;

компилятор ругается, а так

char* kk = new char[10];
kk[0] = 0xff;

нет?

На самом деле, проблема уже описана вот здесь, но сделаю ещё одну маленькую заметку.

После присваивания

char* kk = "345345";

в kk записан некий адрес, по которому хранится строка "345345". Компилятор обычно делает указатель константным, а строку размещает в памяти "read only" (конечно, теоретически туда можно писать, просто операционная система знает, что это неправильно и пресекает попытки записи). Но почему?

Так сделано, в основном, для оптимизаций и упрощения, а также в целях безопасности. Пусть в Вашей программе есть ещё десять мест, где встречается константа "345345". Компилятор не будет создавать 11 копий, а будет использовать один и тот же адрес. А теперь представьте, что вышеуказанное изменение разрешено...

Старые компиляторы (как правило, компилирующие C++ со многими соглашениями из классического Си) этого не делали и часто наблюдались интересные спецэффекты, когда константы изменяли свое значение.

Также нужно различать указатель на константу и константный указатель.

1) Указатель на константу: нельзя менять содержимое объекта, на который указывает указатель, но можно менять содержимое самого указателя (указатель — это переменная, содержащая адрес другой переменной).

/*const */ char * c = "123"; // Указатель на объект, который нельзя менять
c[0] = '0';             // Нельзя, т. к. меняется содержимое указываемого объекта
c = "456";              // Можно, т. к. меняется значение самого указателя

С закомментированным словом const возникнет коварная ошибка времени исполнения программы, а с раскомментированным нормальный компилятор не даст это откомпилировать.

2) Константный указатель: можно менять содержимое объекта, но нельзя менять значение самого указателя. Проще говоря, указатель нельзя переназначить на другой объект, но сами данные, на которые он указывает, менять можно.

char * const c = "123";
c[0] = '0';    // можно
c = "345";     // нельзя, и не откомпилируется

Во втором же коде с new всё понятно, мы выделяем новую память в "куче" и можем делать с ней, что захотим.


теги: c++ программирование ошибка

16.05.2018, 12:17; рейтинг: 37

  свежие записипоиск по блогукомментариистатистика

Наверх Яндекс.Метрика
© PerS
вход