Как декларация функции ANSI C является улучшением в стиле старого Кернигана и Ричи?

With regards to the ANSI C function declaration, how is this an improvement from the old K&R style? I know the differences between them, I just want to know what problems could arise from using the old style and how the new style is an improvement.

Объявление  *в стиле старого стиля* , в частности, не позволяет проводить проверку вызовов во время компиляции.

Например:

```
int func(x, y)
char *x;
double y;
{
     /* ... */
}

```

...

```
func(10, 20);

```

Когда компилятор видит вызов, он не знает типы параметров функции  `func` , поэтому он не может диагностировать ошибку.

В отличие от этого:

```
int better_func(char *x, double y) {
    /* ... */
}

```

...

```
better_func(10, 20);

```

приведет к сообщению об ошибке компилятора (или, по крайней мере, предупреждению).

Другое усовершенствование: прототипы позволяют иметь функции с параметрами типа  `float` , а целочисленных типов более узкие, чем  `int`  (типы  `char`  и два  `short` ). Без прототипа  `float`  продвигается до  `double` , а узкие целые типы повышаются до  `int`  или  `unsigned int`  , С прототипом аргумент  `float`  передается как  `float`  (если функция не является переменной, например  `printf` ), и в этом случае применяются старые правила к вариационным аргументам).

Документ  [C Обоснование](http://www.open-std.org/jtc1/sc22/wg14/www/C99RationaleV5.10.pdf)  обсуждает это в разделе 6.7 .5.3, вероятно, лучше, чем у меня:

>  Механизм прототипа функции является одним из наиболее полезных дополнений
>   на язык C. Эта функция, конечно, имеет прецедент во многих
>   на языках Алгола за последние 25 лет. Конкретная форма
>   принятая в стандарте, во многом основана на C ++. 
> 
> 
>   
>    Прототипы функций обеспечивают мощную ошибку времени перевода
>   возможности обнаружения. В традиционной практике C без прототипов это
>   для переводчика крайне сложно обнаружить ошибки (неверные
>   количество или тип аргументов) в вызовах функций, объявленных в другом
>   исходный файл. Обнаружение таких ошибок произошло либо во время выполнения
>   или с помощью вспомогательных программных средств. 
> 
> 
>   
>    В вызовах функций не входит в объем прототипа функции, integer
>   аргументы имеют  *целые рекламные акции*  и  **float** 
>   аргументы расширяются до  **double** . Это невозможно в таком вызове
>   для передачи непрореагировавшего аргумента  **char**  или  **float** . функция
>   прототипы дают программисту явный контроль над функцией
>   преобразование типа аргумента, так что часто неуместные и
>   иногда неэффективные правила расширения по умолчанию для аргументов могут быть
>   подавлено реализацией. 
> 
> 

Есть больше; пошли читать.



A non-defining function *declaration* in K&R looks as follows

```
int foo();

```

и вводит функцию, которая принимает  *неуказанное*  количество аргументов. Проблема с таким стилем объявления очевидна: он не указывает ни количество параметров, ни их типы. Компилятор не может проверить правильность вызова в отношении количества аргументов или их типов в точке вызова. Компилятор не может выполнить преобразование типа аргумента или сообщение об ошибке и ошибке в ситуациях, когда тип аргумента не соответствует ожидаемому типу параметров.

A function declaration, which is used as a part of function *definition* in K&R looks as follows

```
int foo(a, b) 
int a;
char b;
{ ...

```

Он определяет количество параметров, но не указывает их типы. Более того, даже несмотря на то, что количество параметров, по-видимому, отображается этим объявлением, оно по-прежнему формально объявляет  `foo`  так же, как  `int foo ();`  делает, что означает, что вызов поскольку  `foo (1, 2, 3, 4, 5)`  по-прежнему не является нарушением ограничения.

Новый стиль, то есть декларация с прототипом, лучше по понятным причинам: он предоставляет как количество, так и типы параметров. Это заставляет компилятор проверить правильность вызова (в отношении количества и типов параметров). И это позволяет компилятору выполнять неявные преобразования типов из типов аргументов в типы параметров.

There are other, less obvious benefits provided by prototype declarations. Since the number and types of function parameters are known precisely to both the caller and the function itself, it is possible to choose the most efficient method of passing the arguments (the calling convention) at the point of the call without seeing the function definition. Without that information K&R implementations were forced to follow a single pre-determined "one size fits all" calling convention for all functions.