ПрограммированиеEmbedded C разработчик

Опишите особенности работы с модификатором const для параметров функции и локальных переменных в C. Как const влияет на передачу указателей и ссылок на данные, и в чём разница между различными модификациями const в объявлениях функции?

Проходите собеседования с ИИ помощником Hintsage

Ответ

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 для входного буфера. Библиотека попыталась изменить данные в константной строке, что вызвало падение на некоторых ОС и долгие разбирательства об источнике проблемы.