导言
最近在看《A Retargetable Compiler Design and Implementation》(可变目标C编译器设计与实现),由于鄙人资历尚浅,没有见过上古版本的C语言函数的样子,看这本书第一章的时候,直接懵逼。举个例子,函数的样子如下:
为了不让各位和我有类似的经历,因此打算写个文章记录一下,也算学习一下历史。
本文以简略的语言概括了参考文献的主要内容,如果有朋友想进一步了解,可以详细阅读参考文献。
C语言函数的发展
众所周知,C语言诞生与70年代的贝尔实验室(Bell laboratories),Brian Kerninghan 和 Dennis Ritchie两位大牛C 经典著作 The C Programming Language ,因为该书影响甚广,因此最早的C语言就以书中写法为标准,被称为K&R 标准(源自于两位作者的姓的首字母)。
那个时候C语言的函数写法是这样的:
//K&R 标准
add(a, b)
{
return a + b;
}
大家一定很好奇,为什么没有数据类型,因为早期的C语言并不关注数据的类型,所有的数据类型都会当成int型处理,因此写与不写是一样的,可以省略类型,这样既方便处理,又可以加快编译的速度。
如果加上类型的话是这样的:
//K&R 标准
int add(a, b)
int a;
int b;
{
return a + b;
}
这也就是在我们书中出现的写法,后来随着C语言的广泛应用,逐渐衍生出了多个版本,每个版本都已自己特有的数据类型,而数据类型的处理也不再是简单都按照int处理,这时,人们觉得有必要将C语言进行标准化了。
1983 年,美国国家标准化组织(American National Standard Institute,ANSI) 成立 C 语言工作小组,开始进行标准化工作。
1989 年,C 语言标准草案被 ANSI 委员会接纳。这个 C 语言标准就叫 C89,又叫 ANSI C。
在这之后C语言函数的写法就变成了我们今天熟悉的样子:
//ANSI C 标准
int add(int a, int b;)
{
return a + b;
}
除此之外 ANSI C最大的改变就是函数原型,又叫函数声明,对于K&R标准来说,函数声明是不检查参数类型的,只检查参数名称,但是ANSI C标准将其作为一个整体检查。
K&R C 的原型:
//K&R C 标准
char* strcpy();
就变成了:
//ANSI C 标准
char* strcpy(char* dst, const char* src);
ANSI C 的函数原型其实是从 C++ 借鉴过来的。C++ 扩展了最初的 C 语言,添加了面向对象、模板、函数重载等功能。对于 C++ 的函数重载,只有函数的名字是不够的,需要跟参数类型一起生成链接名字,这个过程称为 name mangling。另外添加函数原型,可以让编译器检查函数调用类型和参数个数是否有错。K&R C 的函数调用语句是不作任何检查的,需要程序员自己注意。