Вызовы функций C: понимание правила "implicit int" - PullRequest
3 голосов
/ 22 ноября 2011

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

    sum += "the function"(line);

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

Я заранее прошу прощения за неоднозначный вопрос, но что это значит?

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

Ответы [ 3 ]

10 голосов
/ 22 ноября 2011

K & R2 охватывает версию языка 1989/1990 гг. Текущий стандарт ISO C, опубликованный в 1999 2011, исключает правило "implicit 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, и если удовлетворены несколько других условий), но для этого нет веских причин.

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

7 голосов
/ 22 ноября 2011

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

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

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

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

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

0 голосов
/ 22 ноября 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...