2010-06-22 4 views
34

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

+1

Можете ли вы привести пример каждого стиля? –

+2

Связанный с этим вопрос: http://stackoverflow.com/questions/1630631/what-is-useful-about-this-c-syntax – sharptooth

+1

Это «K & R», а не «knr» (я исправил вопрос для вас) , что означает Керниган и Ричи и обычно относится к синтаксису С, описанному в их книжной книге на C около 1978 года, * Язык программирования C *. Эта статья может быть вам полезна: http://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C –

ответ

54

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; 
} 
+13

Использование синтаксиса K & R с типом 'void *' является анахронизмом, поскольку K & R C не * имеют * 'void *'. – caf

+3

@caf Нет, я использовал нестандартное расширение для языка :-) – Wizard

+3

На самом деле это определение функции K & R, а не объявление функции K & R. –

19

Наследие K Заявления/Определения &-Style 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 отмечает в this answer аналогичный вопрос о том, что этот синтаксис является устаревшим, но все еще законным с 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; 
} 
+1

Вам нужно уточнить, что вы подразумеваете под «более старыми версиями C». Вы говорите: _Дополнительные версии языка C не требуют полнофункциональных прототипов, но все еще требуют прямого объявления функции до того, как ее можно было бы назвать. Но более старые версии C, означающие pre-standard C, не имели прототипов вообще и не требовал прямого объявления функции до ее вызова. Даже C89/C90 не требовали таких передовых деклараций. Это C99 требовало объявления функций (но все же не обязательных прототипов) перед использованием. –

+0

@JonathanLeffler Спасибо за советы, я прочитал немного больше (в основном статью Википедии о эпохе K & R C) и очистил его, я думаю, что он должен быть исторически точным сейчас. –

0

Я просто хочу добавить, что в традиционном K & модификаторов типа R типа для функций, возвращающих int значения Арена» t даже необходимо.

Рассмотрим современные С11 обозначения простой программы 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, если его значение было использовано.

--source: https://en.wikipedia.org/wiki/C_(programming_language)#K.26R_C

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

+2

И для мазохиста вы можете иметь «main (argc, argv) char ** argv; {...} ', поскольку тип аргументов без явной спецификации типа был, по умозаключению,' int'. Кроме того, 'function (a, b, c, d) char * d, double c, a; {...} 'тоже было хорошо; имена не должны быть указаны в разделе типа в том порядке, в котором они отображаются в списке аргументов. –