const в языке C позволяет ограничивать модифицируемость объекта. При работе с параметрами функции это помогает защитить данные от случайного изменения. Ключевое отличие в объявлении зависит от того, к чему относится модификатор const и где он находится относительно указателя.
Пример различных объявлений:
void func(const int *ptr); // указатель на константный int void func(int * const ptr); // константный указатель на int void func(const int * const ptr); // константный указатель на константный int
const int *ptr — данные неизменяемы, сам указатель можно переназначить.int *const ptr — данные изменяемы, но указатель нельзя переназначить.const int *const ptr — ни данные, ни указатель нельзя изменить внутри функции.Правильное использование const: позволяет:
void print_array(const int *arr, size_t n) { for (size_t i = 0; i < n; ++i) { printf("%d ", arr[i]); // arr[i] = 10; // ошибка: попытка изменить const данные } }
Вопрос: Можно ли присвоить адрес константной переменной обычному указателю?
Ожидаемо неверный ответ: "Да, если убрать const в объявлении указателя, компилятор позволяет."
Правильный ответ: Допустимо "понижение const" только с явным приведением типов (casting), но это приводит к undefined behavior при попытке изменить объект, объявленный как const. Так делать нельзя — это нарушает семантику const и приводит к ошибкам времени выполнения.
Пример:
const int x = 5; int *ptr = (int*)&x; *ptr = 10; // UB: изменение const-объекта
История
В крупном проекте программист попытался обойти защиту const, кастовав const-указатель к обычному и модифицировав данные в read-only-сегменте памяти. На некоторых платформах это привело к аварийному завершению программы (segmentation fault), на других — к незаметным ошибкам, сложным для отладки.
История
В библиотеке для работы с массивом разработчик забыл объявить параметры как const. В результате некорректный вызов функции нечаянно изменил исходные данные, что привело к рассинхронизации состояния массива и серьезным багам в следующих блоках обработки.
История
При написании callback-функции, передаваемой в чужую библиотеку, забыли специфицировать const для входного буфера. Библиотека попыталась изменить данные в константной строке, что вызвало падение на некоторых ОС и долгие разбирательства об источнике проблемы.