Должен объявить прототип функции в C?
Я отчасти новичок в C (у меня есть предшествующий Java, С# и некоторый опыт на С++). В C, нужно ли объявлять прототип функции или может компилироваться код без него? Это хорошая практика программирования? Или это просто зависит от компилятора? (Я запускаю Ubuntu 9.10 и использую компилятор GNU C или gcc в среде Code:: Blocks IDE)
Ответы
Ответ 1
В ANSI C (что означает C89 или C90), вам не нужно объявлять прототип функции; однако использовать их лучше всего. Единственная причина, по которой стандарт позволяет вам не использовать их, - это обратная совместимость с очень старым кодом.
Если у вас нет прототипа, и вы вызываете функцию, компилятор выведет прототип из параметров, которые вы передаете функции. Если вы объявите функцию позже в том же компиляционном блоке, вы получите ошибку компиляции, если подпись функции отличается от того, что догадался компилятор.
Хуже того, если функция находится в другом модуле компиляции, нет способа получить ошибку компиляции, так как без прототипа нет возможности проверить. В этом случае, если компилятор ошибается, вы можете получить поведение undefined, если вызов функции вызывает разные типы в стеке, чем ожидает функция.
Конвенция должна всегда объявлять прототип в заголовочном файле, который имеет то же имя, что и исходный файл, содержащий эту функцию.
В C99 или C11 стандартное C требует объявления функции в области до вызова любой функции. Многие компиляторы не применяют это ограничение на практике, если вы не заставляете их делать это.
Ответ 2
Никогда не требуется объявлять прототип для функции в C, ни в "старом" C (включая C89/90), ни в новом C (C99). Тем не менее, существует значительная разница между C89/90 и C99 в отношении объявлений функций.
В C89/90 нет необходимости объявлять какую-либо функцию вообще. Если функция не объявлена в точке вызова, компилятор "угадывает" (записывает) декларацию неявно из типов аргументов, переданных в вызове, и предполагает, что тип возврата int
.
Например
int main() {
int i = foo(5);
/* No declaration for `foo`, no prototype for `foo`.
Will work in C89/90. Assumes `int foo(int)` */
return 0;
}
int foo(int i) {
return i;
}
В C99 каждая функция, которую вы вызываете, должна быть объявлена перед точкой вызова. Тем не менее, по-прежнему нет необходимости заявлять об этом с помощью прототипа. Также будет работать декларация, отличная от прототипа. Это означает, что в C99 правило "неявное int
" больше не работает (для предполагаемых типов возвращаемых функций в этом случае), но типы параметров все еще можно угадать из типов аргументов, если функция объявлена без прототипа.
Предыдущий пример не будет компилироваться в C99, так как foo
не объявляется в точке вызова. Тем не менее, вы можете добавить объявление без прототипа
int foo(); /* Declares `foo`, but still no prototype */
int main() {
int i = foo(5);
/* No prototype for `foo`, although return type is known.
Will work in C99. Assumes `int foo(int)` */
return 0;
}
...
и введите действительный код C99.
Тем не менее, всегда рекомендуется зарекомендовать прототип функции, прежде чем вы ее назовете.
Дополнительная заметка: Я сказал выше, что никогда не требуется объявлять прототип функции. На самом деле для некоторых функций это требование. Чтобы правильно вызвать переменную функцию в C (printf
например), функция должна быть объявлена прототипом до точки вызова. В противном случае поведение undefined. Это относится как к C89/90, так и к C99.
Ответ 3
это не обязательно, если функция определена до ее использования.
Ответ 4
Это не требуется, но плохой практикой не использовать прототипы.
С прототипами компилятор может убедиться, что вы правильно вызываете функцию (используя правильное число и тип параметров).
Без прототипов это возможно:
// file1.c
void doit(double d)
{
....
}
int sum(int a, int b, int c)
{
return a + b + c;
}
и это:
// file2.c
// In C, this is just a declaration and not a prototype
void doit();
int sum();
int main(int argc, char *argv[])
{
char idea[] = "use prototypes!";
// without the prototype, the compiler will pass a char *
// to a function that expects a double
doit(idea);
// and here without a prototype the compiler allows you to
// call a function that is expecting three argument with just
// one argument (in the calling function, args b and c will be
// random junk)
return sum(argc);
}
Ответ 5
В C, если мы не объявляем прототип функции и не используем определение функции, нет проблем, и программа компилирует и генерирует вывод, если тип возвращаемого значения функции является "целым числом". Во всех других условиях появляется ошибка компилятора. Причина в том, что если мы вызываем функцию и не объявляем прототип функции, тогда компилятор генерирует прототип, который возвращает целое число, и он ищет аналогичное определение функции. если прототип функции совпадает, то он успешно компилируется. Если тип возвращаемого значения не является целым числом, то прототипы функций не совпадают и генерируют ошибку. Поэтому лучше объявить прототип функции в файлах заголовков.
Ответ 6
C позволяет вызывать функции, даже если они ранее не были объявлены, но я настоятельно рекомендую вам объявить прототип для всех функций перед их использованием, чтобы компилятор мог сохранить вас, если вы используете неправильные аргументы.
Ответ 7
Вы должны поместить объявления функций в файл заголовка (X.h) и определение в исходный файл (X.c). Тогда другие файлы могут #include "X.h"
и вызвать функцию.
Ответ 8
Прототип функции не является обязательным в соответствии со стандартом C99
.
Ответ 9
Не обязательно объявлять функцию для компиляции вызывающего кода. Однако есть оговорки. Предполагается, что необъявленная функция возвращает int
, и компилятор сначала выдаст предупреждения о незакрытой функции, а затем о любых несоответствиях в типе возвращаемого типа и типах параметров.
Сказав, что очевидно, что правильное объявление функций с прототипами является гораздо лучшей практикой.
Ответ 10
Выберите "Меню параметров", а затем выберите "Компилятор". С++
Опции. В появившемся диалоговом окне выберите "CPP всегда"
в разделе "Использовать параметры компилятора С++".
Снова выберите "Меню параметров", затем выберите "Окружающая среда |
Редактор. Убедитесь, что расширение по умолчанию - "C", а не
"CPP.