Объявление функции: K&R против ANSI

Каковы различия между объявлением функции K&R и объявлением функции ANSI?

3 ответа

Синтаксис 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; 
}

Устаревшие объявления и определения в стиле 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's 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 для функции, которая принимает неизвестное число параметров неизвестного типа.

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

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

Правильный способ объявить и определить функцию без параметров, конечно:

// 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;
}

Я просто хочу добавить, что в традиционных модификаторах типа стиля 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 только функции, которые возвращали не-int значение, должны были быть объявлены, если они использовались до определения функции; предполагается, что функция, используемая без какого-либо предыдущего объявления, возвращает тип int, если используется ее значение.

--источник: https://en.wikipedia.org/wiki/C_(programming_language)

Возможно, это унаследованный стиль кодирования, и его следует избегать из-за проблем с ясностью, но довольно часто старые учебники по алгоритму предпочитают этот вид стиля K & R.

Другие вопросы по тегам