在我出生之前,C语言是什么样子的?

9
这里有一个问题,C语言(K&R C)最初是什么样子的?这个问题是关于C语言最初的十年或二十年的。

我知道,我听过我的大学教授说,C语言没有我们今天使用的ANSI C标准库。他们曾经用汇编写IO例程!第二件事是,K&R书籍是程序员阅读的最佳书籍之一,这就是我的教授告诉我们的 :)

我想了解更多关于好老C的信息。例如,与ANSI C相比,你知道它的主要区别是什么,或者C如何改变程序员对编程的看法?


仅供记录,我主要阅读了这两篇论文后才提出这个问题:

它们都是关于C++的,我知道!这就是为什么我想了解更多关于C的信息,因为这两篇论文是关于C++如何从C中诞生的。我现在正在向SO大师们询问C语言在此之前的情况。感谢Lazarus指出了K&R的第一版,但我仍然渴望从SO大师们那里了解更多关于C的信息 ;)。


2
也许有点不公平,为什么不去找一本K&R书的第一版呢?那应该能让你了解过去的好日子是什么样子的。 - Lazarus
@Wbdvlpr,我和你一样老,至少根据你的SO个人资料上写的是这样 :) - Khaled Alshaya
注意:我要求真实用户的经验。我读了很多Stroustrup关于C++的文章,而C是你在Stroustrup的论文中经常遇到的语言之一 :) - Khaled Alshaya
请参见http://stackoverflow.com/questions/650351/your-first-c-compiler(不是重复内容)。 - starblue
11个回答

12

首先,没有函数原型的烦恼。 main() 声明如下:

/* int */ main(c,v)
int c;
char *v[];
{
    /* Do something here. */
}

那时候没有那些花里胡哨的双斜杠注释,也没有枚举。真正的男人使用 #define

啊,想起那些美好的日子让我感到泪流满面 :-)


19
过去的好日子,一切都更差,因此更好。 - Stefano Borini
6
实际上,返回类型也被省略了。早期的C语言总是返回一个单词。并且int参数是默认的,所以一个简单的"main(c,v)charv[];{/...*/}"是典型的。 - Andy Ross
我忘记了那一部分,@Andy。 - paxdiablo
"真正的男人使用 #define。" 今天人们使用这样花哨的东西,如const变量或内联函数,甚至是 _lambdas_,天哪!这让我想起来,我现在想要一杯lambada :-) - Johannes Rudolph

7

3

以下是一个ANSI C改变的好处之一的代码示例:

double GetSomeInfo(x)
int x;
{
    return (double)x / 2.0;
}

int PerformFabulousTrick(x, y, z)
int x, int y;
double z;
{
    /* here we go */
    z = GetSomeInfo(x, y); /* argument matching?  what's that? */
    return (int)z;
}

1
你忘记在返回参数周围加上括号了。一些早期的ANSI编译器实际上需要它们。 ;) - Bob Kaufman
是的,那时候生活很糟糕。因为我使用的C编译器是由K&R编写的(当我学习C语言时,我在贝尔实验室工作),所以我从未养成过括号的习惯。 - plinth
我个人从来不太喜欢括号。它们似乎在当时成为了一种被广泛接受的风格,尽管许多来源都强调“避免不必要的括号”,这总是让我感到困扰。一些编译器将return()实现为函数调用,这只会增加混淆。 - Bob Kaufman

3
从个人经验来看,我使用的前两款C编译器/开发环境分别为DeSmet C(16位MS-DOS命令行)和Lattice C(也是16位MS-DOS命令行)。 DeSmet C附带了自己的文本编辑器(see.exe)和库-非标准函数如scr_rowcol()用于定位光标。即使那时,某些函数也是标准的,例如printf(),fopen(),fread(),fwrite()和fclose()
当时的一个有趣特点是,您可以在四种基本内存模型之间进行选择-S、P、D和L。多年来出现了其他变化,但这些是最重要的。 S是“小”模型,对代码和数据都采用16位寻址,每个限制为64K。 L使用24位寻址,这是一个16位段寄存器和一个16位偏移寄存器来计算地址,将您限制为1024K的地址空间。当然,在16位的DOS世界中,您被限制在物理限制640K上。 P和D是两种模式之间的折衷方案,其中P允许24位(640K)代码和64K数据,而D允许64K代码和640K数据寻址。

值得庆幸的是,Lattice决定尽可能使体验类似于Unix,这得益于MS-DOS 2.0也采用了相同的方式。当微软获得Lattice编译器的许可时,他们也做到了同样的事情。 - kdgregory
1
请注意,内存模型是微软的发明。Unix C从未有过这样的怪物。 - Jay
2
实际上,它们是英特尔的发明。主流Unix一直有幸运地在处理器架构上运行,具有连续(通常很大)的地址空间:PDP-11、VAX、68000、80386等等。除非你要限制自己只使用64k数据段,否则你需要有一些机制来寻址8086中其余1M的内存。我没有使用过早期的英特尔C编译器(我不认为它来自Lattice或Microsoft),但我怀疑它具有某种显式分段控制。 - kdgregory

3

谢谢Nathan。如果我想了解更多关于这个主题的内容,维基百科页面实在太简略了。 - Khaled Alshaya
当然,我也注意到了..就在我发布后。:( - Nathan Taylor

3

我第一次在1986年开始使用VAX/VMS上的C语言。以下是我记得的不同之处:

  • 没有原型——函数定义和声明写作:
    int main() /* 没有void来指定空参数列表 */
    {
      void foo(); /* 声明中没有参数列表 */
      ...
    }
    ...
    void foo(x,y)
      int x;
      double y;
    {
      ...
    }
  • 没有通用(void)指针类型;所有的*alloc()函数返回char *,这也是为什么有些人仍然强制转换malloc()返回值的原因;在ANSI之前的编译器中,你必须这样做;

  • 可变参函数的处理方式不同;没有任何固定参数的要求,并且头文件的名称也不同(varargs.h而不是stdarg.h);

  • 随着C99标准的推出,math.h添加了很多内容,特别是在数字工作方面,80年代的C语言并不是最好的工具;

  • 库不是标准化的;几乎所有的实现都有stdio、math、string、ctype等版本,但是其内容在不同的实现中可能不相同。


我也是一个VAX/VMS的人。在Unix和PC领域,从main()返回0意味着一切正常。但是VMS将返回值解释为标准错误代码,其中奇数值是好的,偶数值是坏的。移植的程序总是以“访问冲突”消息退出,因为这就是系统消息表中0映射到的内容。即使使用ANSI,你也不能return EXIT_SUCCESS,你必须使用exit(EXIT_SUCCESS);,然后添加一个/*NOTREACHED*/注释来满足lint,最后return 0;以满足编译器警告。 - Adrian McCarthy
<varargs.h>是相当晚期的开发;在此之前,使用了许多更加可疑的技术。 - Jonathan Leffler

2
由于显而易见的原因,核心语言先于库出现,但如果你拿到1978年出版的K&R第一版副本,你会发现这个库非常熟悉。此外,C最初用于Unix开发,并且库连接到操作系统的I / O服务。因此,我认为您教授的说法可能是虚构的。

最明显的区别在于函数的定义方式:

VOID* copy( dest, src, len )
    VOID* dest ;
    VOID* src ;
    int len ;
{
   ...
}

代替:
void* copy( void* dest, void* src, int len )
{
    ... 
}

例如。请注意VOID的使用; K&R C没有void类型,通常VOID是定义为int*的宏。不用说,为了使这个工作,早期编译器中的类型检查是宽容的。从实际角度来看,C语言验证代码的能力很差(主要是由于缺乏函数原型和弱类型检查),因此像lint这样的工具非常受欢迎。
在1978年,《C程序设计语言》一书的定义就是K&R书。在1989年,它被ANSI标准化,后来被ISO标准化,第二版不再被视为语言定义,并且基于ANSI C。在我看来,它仍然是关于C最好的书,也是一本好的编程书籍。 Wikipedia上有一个简短的描述,可能会有所帮助。你最好得到一本K&R的第一版拷贝,不过,我不建议用它来学习C,应该得到一本第二版。

2

0

16位整数在旧日非常普遍。


0

我在20世纪80年代初开始使用C语言。我发现现在和当时最大的区别是早期的C语言没有函数原型,正如有人指出的那样。我所使用过的最早的C语言几乎与今天的标准库相同。如果有一段时间C语言没有printf或fwrite,那就是在我之前了!我是从原始的K&R书中学习C语言的。它确实是一部经典之作,并证明技术精湛的人也可以成为优秀的作家。我相信你可以在亚马逊上找到它。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接