Каковы различия между объявлением функции K & R и объявлением функции ANSI?
Объявление функции: K & R vs ANSI
Ответ 1
Синтаксис K & R устарел, вы можете пропустить его, если вам не нужно поддерживать очень старый код.
// K&R syntax
int foo(a, p)
int a;
char *p;
{
return 0;
}
// ANSI syntax
int foo(int a, char *p)
{
return 0;
}
Ответ 2
Устаревшие объявления K & R-стиля/определения
Когда Керниган и Ритчи впервые опубликовали "Язык программирования C", C еще не предлагал полнофункциональные прототипы. Передовые декларации функций существуют, но с единственной целью указывать тип возврата. Для функций, возвращаемых int
, они не требовались до C99.
В соответствии с C89 было добавлено понятие прототипа функции, которое также указывает типы параметров (и, неявно, их число). Поскольку прототип также является объявлением функции, неофициальный термин "объявление функции K & R" иногда используется для объявления функции, которое также не является прототипом.
// K&R declarations, we don't know whether these functions have parameters.
int foo(); // this declaration not strictly necessary until C99, because it returns int
float bar();
// Full prototypes, specifying the number and types of parameters
int foo(int);
float bar(int, float);
// K&R definition of a function
int foo(a)
int a; // parameter types were declared separately
{
// ...
return 0;
}
// Modern definition of a function
float bar(int a, float b)
{
// ...
return 0.0;
}
Декларация о случайности K & R
Стоит отметить, что новички на C могут случайно использовать объявления K & R, когда они намереваются использовать полный прототип, потому что они могут не понимать, что пустой список параметров должен быть указан как void
.
Если вы объявляете и определяете функцию как
// Accidental K&R declaration
int baz(); // May be called with any possible set of parameters
// Definition
int baz() // No actual parameters means undefined behavior if called with parameters.
// Missing "void" in the parameter list of a definition is undesirable but not
// strictly an error, no parameters in a definition does mean no parameters;
// still, it better to be in the habit of consistently using "void" for empty
// parameter lists in C, so we don't forget when writing prototypes.
{
// ...
return 0;
}
... тогда вы фактически не дали прототип функции, которая не принимает никаких параметров, а объявляет в K & R-style для функции, которая принимает неизвестное количество параметров неизвестного типа.
AnT отмечает в этот ответ к аналогичному вопросу о том, что этот синтаксис устарел, но по-прежнему является законным с C99 (и эта функция указывает на функции с неизвестным числом и тип параметров по-прежнему имеет потенциальные приложения, хотя и с высоким риском поведения undefined); как таковые, совместимые компиляторы будут, в лучшем случае, вызывать предупреждение, если функция объявлена или вызвана без надлежащего прототипа.
Функции вызова без прототипов менее безопасны, поскольку компилятор не может проверить, что вы правильно указали количество и типы параметров в правильном порядке; undefined поведение, если вызов на самом деле не правильный.
Правильный способ объявления и определения функции без параметров, конечно же:
// Modern declaration of a parameterless function.
int qux(void); // "void" as a parameter type means there are no parameters.
// Without using "void", this would be a K&R declaration.
// Modern definition of a parameterless function
int qux(void)
{
// ...
return 0;
}
Ответ 3
Я просто хочу добавить, что в традиционных модификаторах типа K и R для функций, возвращающих значение int
, даже не нужно.
Рассмотрим современную нотацию C11 простой программы HelloWorld:
int main(int argc, char **argv) {
printf("hello world\n");
return 0;
}
Это эквивалентно стилю нотации K и R:
main(argc, argv)
int argc;
char **argv;
{
printf("hello world\n");
return 0;
}
Обратите внимание, что int
до main()
игнорируется, но код все еще компилируется. Это часть определения K и R.
Цитата Википедия:
В ранних версиях C только функции, которые возвращали значение non-int, которое необходимо было объявить, если оно используется до определения функции; предполагается, что функция, используемая без какого-либо предыдущего объявления, возвращает тип int, если его значение было использовано.
- источник: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C
Это, возможно, устаревший стиль кодирования, и его следует избегать из-за проблем с ясностью, но довольно часто старые алгоритмы алгоритма поддерживают этот тип стиля K и R.