ANSI C函数声明如何改进旧的Kernigan和Ritchie风格?

Ric*_*ray 5 c

关于ANSI C函数声明,这是如何从旧的K&R风格改进的?我知道他们之间的差异,我只是想知道使用旧款式会出现什么问题以及新款式如何改进.

Kei*_*son 8

特别是旧式函数声明不允许对调用进行编译时检查.

例如:

int func(x, y)
char *x;
double y;
{
     /* ... */
}
Run Code Online (Sandbox Code Playgroud)

...

func(10, 20);
Run Code Online (Sandbox Code Playgroud)

当编译器看到调用时,它不知道函数的参数类型func,因此无法诊断错误.

相比之下:

int better_func(char *x, double y) {
    /* ... */
}
Run Code Online (Sandbox Code Playgroud)

...

better_func(10, 20);
Run Code Online (Sandbox Code Playgroud)

将导致编译器错误消息(或至少一个警告).

另一个改进:原型使得可以使用类型参数float和比int(3 char种类型和两种short类型)更窄的整数类型的函数.没有原型,float被提升为double,并且窄整数类型被提升为int或者unsigned int.使用原型,float参数作为a传递float(除非函数是可变参数,例如printf,在这种情况下,旧规则适用于可变参数).

C原理文件讨论这部分6.7.5.3,可能比我更好:

函数原型机制是C语言最有用的补充之一.当然,这一特征在过去25年来的许多Algol派生语言中都有先例.标准中采用的特定形式在很大程度上基于C++.

函数原型提供强大的转换时错误检测功能.在没有原型的传统C实践中,转换器在调用另一个源文件中声明的函数时很难检测错误(错误的数量或类型的参数).在运行时或通过使用辅助软件工具检测到此类错误.

在不在函数原型范围内的函数调用中,整数参数应用了整数提升,并且浮点 参数被加宽为double.在这样的调用中不可能传递未转换的charfloat参数.函数原型为程序员提供了对函数参数类型转换的显式控制,因此实现可以抑制参数的通常不适当且有时效率低的默认扩展规则.

还有更多; 去读它.

  • @templatetypedef:不一定.旧式非原型函数*声明*不包括函数体,因此它不提供参数类型信息.示例:`some_header.h`中的`int func();`.完整的*定义*确实提供了该信息,但(a)它可能不在同一个源文件中,并且(b)即使编译器也不需要使用它.使用无效参数调用非原型函数具有未定义的行为; 它无需诊断. (2认同)