C вызовы функции: Понимание правила "неявного int" - программирование

C вызовы функции: Понимание правила "неявного int"

Если "функция" была скомпилирована отдельно, несоответствие не будет обнаружено, "функция" вернет двойной, который main будет рассматривать как int... В свете того, что мы говорили о том, как должны совпадать объявления это может показаться удивительным. Причина, по которой может возникнуть несоответствие, заключается в том, что если прототип функции отсутствует, функция неявно объявляется ее первым появлением в выражении, например

    sum += "the function"(line);

Если имя, которое ранее не было объявлено, встречается в выражении и за ним следует левая скобка, он объявляется контекстом как имя функции, предполагается, что функция возвращает int, и ничего не предполагается о ее аргументы.

Извиняюсь заранее за неоднозначный вопрос, но что это значит?

Кстати, это страница 4.3 главы книги Брайана У. Кернигана и Денниса М. Ричи C, 2-е издание.

4b9b3361

Ответ 1

K & R2 охватывает версию языка 1989/1990. Текущий стандарт ISO C, опубликованный в 1999 2011, отменяет правило "неявное int" и требует видимого объявления для любой функции, которую вы вызываете. Компиляторы не обязательно применяют это по умолчанию, но вы должны иметь возможность запрашивать более строгие предупреждения - и вам определенно нужно. В хорошо написанном новом коде правило не имеет значения (но это необходимо для его понимания).

Пример: стандартная функция sqrt() объявлена ​​в <math.h>:

double sqrt(double);

Если вы пишете вызов без требуемого #include <math.h>:

double x = 64.0;
double y = sqrt(x);

Компилятор C90 предположит, что sqrt возвращает int - и он сгенерирует код для преобразования результата с int в double. Результатом будет мусор или, возможно, сбой.

(Вы можете вручную объявить sqrt самостоятельно, но это неправильное решение.)

Так что не делай этого. Всегда включайте любой заголовок, необходимый для любой вызываемой вами функции. Вы можете уйти с вызовом необъявленной функции, если она возвращает int (и если ваш компилятор не применяет строгую семантику C99 или C11, и если выполняется несколько других условий), но нет веских оснований для этого.

Понимание правила "неявного int" по-прежнему полезно для понимания поведения старого или плохо написанного кода, но вы никогда не должны зависеть от него в новом коде.

Ответ 2

Прототипы функций были введены на язык поздно.

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

Это работало отлично для нескольких случаев, когда это было правильно, но это означало, что людям приходилось писать программы в неудобном порядке, чтобы функции никогда не полагались на неизвестные функции, которые не соответствовали этому ожиданию.

Когда прототипы были введены в C89 (aka ANSI C или ISO C), прототипы позволяют компилятору точно знать, какие типы аргументов ожидаются и какие типы результатов будут возвращены.

Настоятельно рекомендуется использовать прототипы функций для всего нового кода; при работе с полностью старой базой кода прототипы могут быть вредными. (Или, если код должен быть скомпилирован в компиляторе pre-ANSI C, тогда вы можете оставить прототипы, чтобы он мог быть построен на древнем программном обеспечении. gcc - это единственное место, которое я видел в долгое время.)

Ответ 3

Он просто заявляет, что если компилятор встречает код, вызывающий неизвестную функцию, то он неявно рассматривает его, как если бы он уже видел объявленный прототип формы int unknown();