Зачем прототипы функций в C спасают вас от скрытых ошибок

0
10

Вам не нужно видеть полное тело функции, чтобы знать, как её вызвать. Вам нужно лишь обещание. Таким обещанием является прототип функции.

В современном C предварительное объявление прототипов обязательно. Оно сообщает компилятору, чего именно ожидает функция: имя, типы аргументов и возвращаемое значение. Без него вы действуете вслепую. А в C слепота обходится дорого.

Скрытая стоимость отсутствия прототипов

Рассмотрите этот фрагмент кода. Он выглядит невинно. Он компилируется. Он выполняется.

Здесь add явно требует два целых числа. Но вызов передаёт только один. Строгий компилятор должен был бы возмутиться. Многие этого не делают. Они по умолчанию предполагают, что возвращаемый тип — int, и полностью игнорируют несоответствие параметров.

Результат? Неправильные ответы. Тихая порча данных. Вы тратите часы на поиск ошибки, которая смотрела на вас прямо в лицо во второй строке.

Это происходит потому, что унаследованное поведение C по умолчанию предполагает, что функции без прототипов возвращают int. Если фактическая функция возвращает float, компилятор неправильно интерпретирует биты. Прототип исправляет это. Он обеспечивает соблюдение контракта.

Обеспечение соблюдения контракта

Разместите прототип в начале. Где-нибудь перед первым вызовом.

Теперь компилятор отмечает ошибку. Он знает, что add требует два аргумента. Он отказывается компилировать вызов с несоответствующими аргументами. Вы экономите часы отладки.

Старый стиль против современного C

Не-ANSI компиляторы — это совсем другая история. Они позволяют использовать прототипы, но с оговоркой. Список параметров должен быть пустым.

Это сообщает компилятору имя и возвращаемый тип. Он ничего не говорит об аргументах. Проверка ошибок не происходит. Вы возвращаетесь к исходной точке.

Современный C (стандарт ANSI) требует явного указания типов в прототипе. Это устраняет неоднозначность. Он выявляет несоответствия типов. Он выявляет отсутствие аргументов. Он выявляет всё.

Практические шаги

  1. Рефакторинг пузырьковой сортировки. Перенесите логику в функцию. Объявите прототип. Передавайте массив и размер явно.
  2. Изоляция ввода. Создайте отдельную функцию для пользовательского ввода. Не загромождайте main. Объявите прототип. Протестируйте его.

Речь не о баллах за стиль. Речь о корректности.

Прототип — это контракт, обеспечиваемый компилятором. Нарушите его, и сборка завершится ошибкой.

Вы можете задаться вопросом, почему это важно, если ваш код работает. Это важно, потому что ошибки времени выполнения сложнее исправлять, чем ошибки времени компиляции. Ошибка компиляции останавливает вас. Ошибка времени выполнения прячется в продакшене.

Разница между надёжной и хрупкой программой часто сводится к этим нескольким строкам в начале. Не пропускайте их.

Компилятор существует, чтобы помогать. Прислушивайтесь к нему.

попередня статтяКак работают серверы: скрытые двигатели интернета
наступна статтяКак работают автоматические дозвонщики: от телемаркетинга до экстренных оповещений