Альтернатива (K&R) синтаксис C для объявления функции по сравнению с прототипами

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

69
задан Deduplicator 16 June 2019 в 10:27
поделиться

5 ответов

The question you are asking is really two questions, not one. Most replies so far tried to cover the entire thing with a generic blanket "this is K&R style" answer, while in fact only a small part of it has anything to do with what is known as K&R style (unless you see the entire C language as "K&R-style" in one way or another :)

The first part is the strange syntax used in function definition

int func(p, p2)
void *p;
int  p2; /* <- optional in C89/90, but not in C99 */
{
  return 0;
}

This one is actually a K&R-style function definition. Other answer have covered this pretty well. And there's not much to it, actually. The syntax is deprecated, but still fully supported even in C99 (except for "no implicit int" rule in C99, meaning that in C99 you can't omit the declaration of p2).

The second part has little to do with K&R-style. I refer to the fact that the function can be called with "swapped" arguments, i.e. no parameter type checking takes place in such a call. This has very little to do with K&R-style definition per se, but it has everything to do with your function having no prototype. You see, in C when you declare a function like this

int foo();

it actually declares a function foo that takes an unspecified number of parameters of unknown type. You can call it as

foo(2, 3);

and as

j = foo(p, -3, "hello world");

ans so on (you get the idea);

Only the call with proper arguments will "work" (meaning that the others produce undefined behavior), but it is entirely up to you to ensure its correctness. The compiler is not required to diagnose the incorrect ones even if it somehow magically knows the correct parameter types and their total number.

Actually, this behavior is a feature of C language. A dangerous one, but a feature nevertheless. It allows you to do something like this

void foo(int i);
void bar(char *a, double b);
void baz(void);

int main()
{
  void (*fn[])() = { foo, bar, baz };
  fn[0](5);
  fn[1]("abc", 1.0);
  fn[2]();
}

i.e. mix different function types in a "polymorphic" array without any typecasts (variadic function types can't be used here though). Again, inherent dangers of this technique are quite obvious (I don't remember ever using it, but I can imagine where it can be useful), but that's C after all.

Finally, the bit that links the second part of the answer to the first. When you make a K&R-style function definition, it doesn't introduce a prototype for the function. As far as function type is concerned, your func definition declares func as

int func();

i.e. neither the types nor the total number of parameters are declared. In your original post you say "... it seems to specify is how many params it uses ...". Formally speaking, it doesn't! After your two-parameter K&R-style func definition you still can call func as

func(1, 2, 3, 4, "Hi!");

and there won't be any constraint violation in it. (Normally, a quality compiler will give you a warning).

Also, a sometimes overlooked fact is that

int f()
{
  return 0;
}

is also a K&R-style function definition that does not introduce a prototype. To make it "modern" you'd have to put an explicit void in the parameter list

int f(void)
{
  return 0;
}

Finally, contrary to a popular belief, both K&R-style function definitions and non-prototyped function declarations are fully supported in C99. The former has been deprecated since C89/90, if I remember correctly. C99 requires the function to be declared before the first use, but the declaration is not required to be a prototype. The confusion apparently stems from the popular terminological mix-up: many people call any function declaration "a prototype", while in fact "function declaration" is not the same thing as "prototype".

145
ответ дан 24 November 2019 в 13:42
поделиться

Это исходный синтаксис K&R до того, как C был стандартизирован в 1989 году. В C89 были представлены прототипы функций, заимствованные из C ++, и исключен синтаксис K&R. Нет причин использовать его (и множество причин не использовать) в новом коде.

1
ответ дан 24 November 2019 в 13:42
поделиться

Это просто старый синтаксис, который предшествует синтаксису "ANSI C", с которым вы, возможно, более знакомы. Обычно он называется « K&R C ».

Компиляторы поддерживают его, чтобы он был полным, и, конечно, чтобы иметь возможность обрабатывать старые кодовые базы.

4
ответ дан 24 November 2019 в 13:42
поделиться

Это пережиток того времени, когда в C не было прототипов для функций. В те времена (я думаю) предполагалось, что функции возвращают int , а все его аргументы - int . Не выполнялась проверка параметров функций.

Вам гораздо лучше использовать прототипы функций на текущем языке C.
И вы должны использовать их в C99 (C89 все еще принимает старый синтаксис

А C99 требует объявления функций (возможно, без прототипа). Если вы пишете новую функцию с нуля, вам нужно предоставить объявление ... сделать ее также прототипом: вы ничего не потеряете и получите дополнительную проверку от компилятора.

1
ответ дан 24 November 2019 в 13:42
поделиться

Это довольно старый синтаксис K&R C (предшествующий ANSI / ISO C). В настоящее время вы не должны больше использовать его (как вы уже заметили его главный недостаток: компилятор не будет проверять типы аргументов за вас). Тип аргумента в вашем примере фактически по умолчанию равен int .

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

foo(p, q) 
{
    return q + p;
}

, которые на самом деле были правильным определением, как типы для foo , p и q по умолчанию int .

17
ответ дан 24 November 2019 в 13:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: