万字详解,讲述C语言发展史的每一个细节

2024-10-16 16:57:07 | 作者: 匿名

1. C语言发展史

任何新事物的出现都不是偶然的,而是时代推动的必然结果。

1.1 C语言有多伟大

如果你问我:C语言有多伟大。然后,我可能想一想,说:我不知道它有多棒,但我知道它很棒。

在这里,我想说一句可能有点片面的话:当今世界,凡是有电的地方,都可能有她(C语言)或者她的后代的影子。

任何低于C的语言都不足以完全抽象计算机系统;任何高于C的语言都可以用C实现。

1.2 C语言之父

Ritchie Bell Labs个人主页地址https://www.bell-labs.com/usr/dmr/www/index.html

丹尼斯·麦阿里斯泰尔·里奇(英语:Dennis MacAlistair Ritchie,1941年9月9日—2011年10月12日),美国计算机科学家。他在黑客圈子里俗称“dmr”。他是C语言的创造者和Unix操作系统的主要开发者。他对计算机领域产生了深远的影响,并与Ken Thompson 一起获得了1983 年图灵奖。

丹尼斯·里奇的人生时间表

麻省理工学院计算机科学系教授马丁评价道:“如果说乔布斯是视觉产品之王,那么里奇就是无形王国的君主。”乔布斯的贡献在于,他非常了解用户的需求和愿望,从而创造出了让当代人快乐的科技产品。然而,为这些产品提供核心部件的却是里奇先生。人们看不到这些组件,但它们每天都在使用。 '

克尼汉评论道:牛顿说他站在巨人的肩膀上,而现在,我们都站在里奇的肩膀上。

1.3 C语言的先辈

为了简洁起见,我(Dennis M.Ritchie)省略了C 本身、其父级B [Johnson 73] 及其祖级BCPL [Richards 79] 的完整描述,仅关注每种语言的特征元素以及它们如何演变。

本文介绍了C 编程语言的发展、对其的影响以及它的创建条件。为了简洁起见,我省略了对C 本身、其父级B [Johnson 73] 及其祖级BCPL [Richards 79] 的完整描述,而是专注于每种语言的特征元素及其演变方式。

https://www.bell-labs.com/usr/dmr/www/chist.html

本文来自C语言之父Dennis M. Ritchie写的一篇关于《C语言发展史》的文章。文章明确指出,C语言是由B和BCPL这两种语言派生出来的。 C语言可以看作是站在巨人的肩膀上,顺应时代潮流。

1.3.1 BCPL语言之父

马丁·理查兹

Martin Richards 的BCPL 参考手册,1967 年https://web.archive.org/web/20080622171914/http://cm.bell-labs.com/cm/cs/who/dmr/bcpl.html

马丁·理查兹(英语:Martin Richards,1940年7月21日),出生于英国,计算机科学家。他是BCPL编程语言的发明者,并开发了TRIPOS操作系统。

1966年,Martin Richard在剑桥大学基于CPL编程语言发明了BCPL编程语言。

1.3.2 B语言之父

肯尼思·莱恩·汤普森

肯尼思·莱恩·汤普森(英语:Kenneth Lane Thompson,1943年2月4日),绰号肯·汤普森(英语:Ken Thompson),美国计算机科学学者、工程师。黑客文化圈通常称他为“ken”。在贝尔实验室工作期间,Thompson 设计并实现了Unix 操作系统。他创建了C 语言的前身B 语言(基于BCPL),并且是Plan 9 操作系统的创建者和开发者之一。他与丹尼斯·里奇一起获得了1983 年图灵奖。

2006年,汤普森加入谷歌并共同设计了Go语言。

1.3.3 一组Ken与Dennis的照片

一天比一天好

站在巨人的肩膀上

坐着的是肯,站着的是丹尼斯。

让自己周围都是优秀的人

不惧得失,做有趣的事

言传身教

感谢Dennis Ritchie给这个世界留下了一本“C语言圣经”

遗憾的是,笔者在大学时是师从谭浩强老师学习C语言的。

丹尼斯与《The C Programming Language》

成就彼此

终于取得了成功

你所做的一切最终都会被世界看到

1999年荣获美国国家技术奖【左一:Ken |左二:丹尼斯|右一:克林顿]

从这些老照片中,我隐约看到几行小字,上面写着:

1.让自己身边都是优秀的人

2. 共同成就

试想一下,它有多重要?

1.4 C语言时间线

计算机语言历史https://www.levenez.com/lang/

从图中的时间线,我们可以清楚地看到C语言的起源和时间节点。

有时不得不说,时势造英雄。 1969年至1971年间,著名的操作系统Unix由肯·汤普森诞生。作为大型系统软件,非常需要一种可靠的高级语言。出现了(当时的低级语言指的是汇编,因为以前的操作系统都是用汇编编写的)。丹尼斯·里奇此时也没闲着。改进了B语言之后,类型化的C语言诞生了(据Ritchie自己说,这种改进后的语言一度被称为NB。即:new B。不过,在我们这些吃瓜群众眼里,它确实是NB )。

1971 年,我开始通过添加字符类型来扩展B 语言,并重写其编译器以生成PDP-11 机器指令而不是线程代码。因此,从B 到C 的过渡是与编译器的创建同时发生的,该编译器能够快速生成足够小的程序,足以与汇编语言竞争。我将稍微扩展的语言称为NB,即“新B”。

1.5 unix时间线

Unix的诞生与C语言的广泛传播和使用密切相关。

上面的时间线只展示了与C 语言同时诞生的前几个Unix 版本(当然,如果你有兴趣,可以查一下Unix 的相关发展历史,绝对会让你大吃一惊。最著名的就是分支:BSD、minix、Linux.)。

接下来我们通过网上找到的一些Unix内核源代码来追溯一下C语言出现的时间。

1.5.1 PDP-Unix

PDP-Unix系统内核代码文件

PDP-7 Unix https://minnie.tuhs.org/cgi-bin/utree.pl?file=PDP7-Unix

可以看到它们基本上都是用汇编语言编写的(文件名后缀.s)。为什么要用“基本”这个词?因为系统中有些命令是用B语言写的。

1.5.2 First Edition Unix

万字详解,讲述C语言发展史的每一个细节

第一版Unix系统内核代码文件

https://minnie.tuhs.org/cgi-bin/utree.pl?file=V1

可以看到,仍然是用汇编语言编写的(文件名后缀.s)。

1.5.3 Second Edition Unix

第二版Unix系统内核代码文件

第二版Unix Unix 的第二版是由Ken Thompson、Dennis Ritchie 等人在贝尔实验室为PDP-11 开发的。它通过更多的系统调用和更多的命令扩展了第一版。这个版本也看到了C语言的开始,它被用来编写一些命令。

https://minnie.tuhs.org/cgi-bin/utree.pl?file=V2

到了这个版本,已经可以看到C语言了。

1.5.4 Unix与C语言

C语言出现在Unix V2版本之后,从Unix V3版本开始,在Unix内核中就可以看到大量用C语言编写的代码。

Rich 表示:到1973 年初,现代C 语言的基础已经完成。 C 语言和编译器足够强大,足以让我们在那年夏天用C 重写PDP-11 的Unix 内核(Unix 的V3 版本)。

到1973 年初,现代C 语言的基本要素已经完成。该语言和编译器足够强大,允许我们在那年夏天用C 语言重写PDP-11 的Unix 内核。

至此,基本可以确定C语言和Unix的大部分核心已经完善。剩下要做的就是可移植性和标准化。

您可能听说过以下故事:Unix 后来被学术界和政府组织使用。正是由于Unix的流行和繁荣,C语言才得到了广泛的传播和使用。

20 世纪80 年代,C 语言的使用广泛传播,编译器几乎适用于所有机器架构和操作系统。特别是,它已成为个人计算机上极其流行的编程工具,无论是在这些机器的商业软件制造商中还是在对编程感兴趣的最终用户中。

在20 世纪80 年代,C 语言的使用广泛传播,几乎所有机器架构和操作系统都可以使用编译器;特别是,它作为个人计算机的编程工具而变得流行,无论是对于这些机器的商业软件制造商还是对编程感兴趣的最终用户。

这就是所谓的相互成就。

一句话概括就是:不惧得失,天天向上,最终达到共同成功。

1.6 第一个C语言编译器是怎样编写的?

不知道你有没有想过。大家都用C语言或者基于C语言的语言来编写编译器。那么世界上第一个C语言编译器是怎么写出来的呢?这不是一个“先有鸡还是先有蛋”的问题……

回顾C语言的历史:Tomphson基于BCPL开发了B语言,Ritchie基于B语言成功开发了现在的C语言。在C被用作系统编程语言之前,Tomphson也用B编写了操作系统。可见,在C语言实现之前,B语言就已经可以投入使用了。因此,第一个C编译器原型完全有可能是用B语言或B语言和PDP汇编语言的混合语言编写的。

我们现在都知道B语言的执行效率比较低,但如果全部用汇编语言编写,不仅开发周期长、维护困难,更可怕的是会失去可移植性高级编程语言所必需的。

因此,早期的C语言编译器采用了一种取巧的做法:先用汇编语言为C语言的子集编写一个编译器,然后利用这个子集递归完成一个完整的C语言编译器。

详细过程如下:首先创建一个只有C语言最基本功能的子集,记为C0语言。 C0语言足够简单,C0编译器可以直接用汇编语言编写。依托C0已有的功能,设计比C0更复杂,但仍然不完整,C语言的另一个子集,C1语言。 C0属于C1,C1属于C。使用C0开发了C1语言的编译器。在C1的基础上,设计了C语言的另一个子集——C2语言。 C2语言比C1更复杂,但它仍然不是完整的C语言。开发了C2语言的编译器.等等,直到CN,CN足够强大。时间足够开发C语言编译器的完整实现。至于这里的N是什么,取决于你的目标语言(这里是C语言)的复杂程度和程序员的编程能力。简单来说,如果你达到了某个子集阶段,并且你可以轻松地使用现有的函数来实现C语言,那么你就找到了N。下图说明了这个抽象过程:

https://zhuanlan.zhihu.com/p/136102461

而这个过程也在Unix V2版本中找到了证据。

Ken Thompson、Dennis Ritchie 和其他人在贝尔实验室为PDP-11 开发了第二个版本的Unix。它通过更多系统调用和更多命令扩展了第一个版本。这个版本还看到了C语言的开始,它被用来编写一些命令。

这里的代码只是一些命令、一些库函数和C编译器的源代码。 c/中的文件来自last1120c.tar.gz 磁带,构成了适用于版本2 Unix 的工作C 编译器。

下载地址:http://minnie.tuhs.org/Archive/Applications/Early_C_Compilers/last1120c.tar.gz

Unix 的第二版是由Ken Thompson、Dennis Ritchie 等人在贝尔实验室为PDP-11 开发的。它通过更多的系统调用和更多的命令扩展了第一版。这个版本还看到了C 语言的开始,它被用来编写一些命令。

这里的代码只是部分命令、部分库函数和C编译器的源码。 c/中的文件来自last1120c.tar.gz 磁带,并形成第二版Unix 的工作C 编译器。

https://minnie.tuhs.org/cgi-bin/utree.pl?file=V2

下载源码并解压后,目录结构如下:

有兴趣的朋友可以下载学习一下。

2. BCPL、B、C语言比较

如果你想找到一种比较编程语言的好方法,那么就是代码。

2.1 3种语言代码示例

下面使用BCPL、B、C语言实现一个简单的程序:程序将a、b、c三个数相加,将结果赋值给sum,最后打印和。

2.1.1 BCPL语言示例

BCPL https://zh.wikipedia.org/wiki/BCPL

GET'libhdr'LETstart()=VALOF{LETa,b,c=1,2,3sum:=a+b+cwriten(sum)}:=该符号是赋值符号。该符号在Go 中也存在,表示函数内的局部变量。这里感觉很有趣的是B语言之父Ken Thompson最初把:=符号改成了=符号。现在,作为Go语言之父之一,他又带回了:=符号(他的命运~)。在从BCPL 到B 的转换中,决定使用单个字符=而不是赋值:=

从BCPL 到B 的过渡中的其他一些调整是出于个人喜好而引入的,其中一些仍然存在争议,例如决定使用单个字符=进行赋值而不是:=。类似地,B 使用/**/来括住注释,而BCPL 使用//来忽略直到行尾的文本。 PL/I 的遗产在这里显而易见。 (C++ 恢复了BCPL 注释约定。)Fortran 影响了声明的语法: B 声明以auto 或static 等说明符开头,后跟名称列表,而C 不仅遵循这种风格,而且通过将其类型关键字放置在声明的开始。

https://www.bell-labs.com/usr/dmr/www/chist.html

2.1.2 B语言示例

B 语言教程https://web.archive.org/web/20070807110157/http://cm.bell-labs.com/cm/cs/who/dmr/btut.html

语言B的语言结构

main(){--statements--}newfunc(arg1,arg2){--statements--}fun3(arg){--morestatements--}B语言代码示例

main(){autoa,b,c,sum;a=1;b=2;c=3;sum=a+b+c;putnumb(sum);}putnumb是一个带参数的库函数,将会打印终端上的数字

2.1.3 C语言示例

#includestdio.hvoidmain(){inta,b,c,sum;a=1;b=2;c=3;sum=a+b+c;printf('%d', sum);}

2.2 示例代码中三者的区别

通过上面的例子可以看出三者的区别:

C语言的写法更接近B语言的BCPL。 B语言是无类型语言,使用word/cell来表示固定长度的位。 C语言是类型化的,有一些你可能感兴趣的东西:

++ 和-- 符号是Thompson 发明的,并且||在C语言中引入:

找了半天,只找到了一些BCPL和B语言的代码片段。至于能不能跑,我就不知道了。 ^_^ 如果想了解三者的具体区别,建议阅读Dennis Ritchie关于《C语言发展史》的文章。 BCPL和B语言的文章也经历了好几个版本迭代(因为网上找到的代码片段在写法上有很多差异。比如维基百科上找到的B代码片段就和以前版本的Unix内核中找到的不一样) B代码片段写法不一样,个人猜测是版本问题。)C语言更接近B语言,或者说是在B的基础上不断添加了很多新的功能(抛砖引玉)。出2个问题: 1.为什么Rich没有像C++一样选择B++这个名字? 2.为什么C++用两个加号而不是一个加号并称之为C+?欢迎有大想法的同学留言)如果有的话!专家认为上面的代码片段有问题或者知道如何运行,可以私聊

3. 历史为什么选择C语言

20世纪60年代后期,贝尔实验室对计算机系统的研究进入了繁荣时期。 Mutlics 项目是麻省理工学院、通用电气和贝尔实验室之间的合作项目,但以失败告终(1969 年左右)。正是在这一时期,Ken Tompson 开始编写Mutlics 的替代品。他希望按照自己的设计构建一个舒适的计算系统(即Unix)。后来,当他写出Unix的第一个版本时,他觉得Unix上需要一种新的系统编程语言,于是他创造了B语言。 B语言是没有类型的C语言。准确地说,B语言是汤普森将BCPL压缩到8K内存中并经过他个人大脑过滤后产生的语言。

由于B语言的一些问题,仅用于编写一些命令工具。正是在这一时期,里奇重新设计并改进了B语言,从而诞生了C语言。

1973年,C语言基本完成,从语言和编译器上来说已经足够了,汤普森和里奇用C语言重写了Unix内核。后来Unix逐渐在一些研究机构、大学和政府机构中流行起来,进而带动了C语言的发展。

1978年,KR编写的《The C Programming Language》出版,进一步推动了C语言的普及。

一句话概括:在正确的时间,正确的地点,出现了正确的人和工具(Unix和C语言的关系有点像GNU和Linux内核的关系,他们都取得了共同的成功) 。

万字详解,讲述C语言发展史的每一个细节

4. 标准C库及代码

经过几次迭代,C语言及其标准成为了今天大家看到的样子。许多C标准库都在其标准中规定,不同的系统有自己不同的代码实现。

当然,Linux内核中也有实现标准C库的代码。让我们欣赏一下它的美丽吧。

4.1 标准C库

ANSI C 总共包括15 个头文件。 1995 年,Normal Addendum 1 (NA1) 批准向C 标准函数库添加三个头文件(iso646.h、wchar.h 和wctype.h)。 C99 标准添加了6 个头文件(complex.h、fenv.h、inttypes.h、stdbool.h、stdint.h 和tgmath.h)。 C11 标准中添加了五个新的头文件(stdalign.h、stdatomic.h、stdnoreturn.h、threads.h 和uchar.h)。

到目前为止,C标准函数库共有29个头文件:

https://www.wikiwand.com/zh-sg/C%E6%A8%99%E6%BA%96%E5%87%BD%E5%BC%8F%E5%BA%AB#/%E5%8F%82% E8%80%83%E6%96%87%E7%8C%AE

4.2 linux/lib/string.c

Linux内核版本:4.18.13

lnux内核地址https://www.kernel.org/

下面列出了三个字符串处理函数strcpy()、strncpy() 和strncat()。该代码由Linus Benedict Torvalds 编写。为什么这么说?看看代码头注释,还是有股熟悉的傻气。看过git源码的人应该也知道,git源码中也有类似的注释。

//SPDX-License-Identifier:GPL-2.0/**linux/lib/string.c**版权所有(C)1991,1992Li

nusTorvalds*//**stupidlibraryroutines..Theoptimizedversionsshouldgenerallybefound*asinlinecodein<asm-xx/string.h>**Thesearebuggyaswell..***FriJun251999,IngoOeser<ioe@informatik.tu-chemnitz.de>*-Addedstrsep()whichwillreplacestrtok()soon(becausestrsep()is*reentrantandshouldbefaster).Useonlystrsep()innewcode,please.***SatFeb092002,JasonThomas<jason@topic.com.au>,*MatthewHawkins<matt@mh.dropbear.id.au>*-Kissedstrtok()goodbye*///.......omitother......//......hereismylovecode.....#ifndef__HAVE_ARCH_STRCPY/***strcpy-Copya%NULterminatedstring*@dest:Wheretocopythestringto*@src:Wheretocopythestringfrom*/#undefstrcpychar*strcpy(char*dest,constchar*src){char*tmp=dest;while((*dest++=*src++)!='\0')/*nothing*/;returntmp;}EXPORT_SYMBOL(strcpy);#endif#ifndef__HAVE_ARCH_STRNCPY/***strncpy-Copyalength-limited,C-string*@dest:Wheretocopythestringto*@src:Wheretocopythestringfrom*@count:Themaximumnumberofbytestocopy**Theresultisnot%NUL-terminatedifthesourceexceeds*@countbytes.**Inthecasewherethelengthof@srcislessthanthatof*count,theremainderof@destwillbepaddedwith%NUL.**/char*strncpy(char*dest,constchar*src,size_tcount){char*tmp=dest;while(count){if((*tmp=*src)!=0)src++;tmp++;count--;}returndest;}EXPORT_SYMBOL(strncpy);#endif#ifndef__HAVE_ARCH_STRLCPY#ifndef__HAVE_ARCH_STRNCAT/***strncat-Appendalength-limited,C-stringtoanother*@dest:Thestringtobeappendedto*@src:Thestringtoappendtoit*@count:Themaximumnumbersofbytestocopy**Notethatincontrasttostrncpy(),strncat()ensurestheresultis*terminated.*/char*strncat(char*dest,constchar*src,size_tcount){char*tmp=dest;if(count){while(*dest)dest++;while((*dest++=*src++)!=0){if(--count==0){*dest='\0';break;}}}returntmp;}EXPORT_SYMBOL(strncat);#endif#ifndef__HAVE_ARCH_STRLCAT//.......omitother......//......hereismylovecode.....第一次跟同学一起看这些代码的时候,他说了一句话:这才叫代码,其他的都是s-h-X-t。现在回想起,自己在实现这些代码时,写了一坨不知道是什么的东西。哎,代码比代码要扔~ 阅读他人代码, 也是一种进步、成长

5. 廉颇老矣, 尚能饭否?

《史记·廉颇蔺相如列传》记载,廉颇被免职后,跑到魏国,赵王想再用他,派人去看他的身体情况,廉颇之仇郭开贿赂使者,使者看到廉颇,廉颇为之米饭一斗,肉十斤,被甲上马,以示尚可用。使者回来报告赵王说:"廉颇将军虽老,尚善饭,然与臣坐,顷之三遗矢(通假字,即屎)矣。"赵王以为廉颇已老,遂不用。 经历过几十年的风雨洗礼,C语言可谓风光无数,这世界上随处可见它的身影。但是,同时在一些人眼里,可能觉得C语言已是暮年(将近50岁)、老矣。如同下图: 如果你真这样想,那你就错了。 TIOBE Index for September 2020 https://www.tiobe.com/tiobe-index/ TIOBE 2020-09 编程语言排行榜告诉你,C语言宝刀未老,还是那个风采耀眼的少年。 个人想说的是,只要计算机还是基于冯诺依曼体系结构,芯片还是基于物理制程。那么,都会有一片C的天空。因为,她知道一个最接近天空的地方(C是最接近汇编、机器语言的高级语言之一)。 任他上层应用改朝换代,我(C语言)自岿然不动。这就是C,我心中的C语言。

总结

最后想说的是:纵使千言万语也说不尽C语言的重要性,这些文字也仅仅只是冰山一角。 鉴于个人能力有限,如有问题或者缺陷,欢迎指正。 参考资料 在整理的过程中,部分参考、引用下面链接地址内容: [1] https://www.bell-labs.com/usr/dmr/www/index.html 里奇贝尔实验室主页 [2] https://www.bell-labs.com/usr/dmr/www/chist.html C语言发展史 [3] https://www.bell-labs.com/usr/dmr/www/1stEdman.html Unix Programmer's Manual [4] https://www.bell-labs.com/usr/dmr/www/bcpl.html Martin Richards's BCPL Manual [5] https://www.levenez.com/lang/ Computer Languages History [6] https://www.levenez.com/unix/ Unix History [7] https://minnie.tuhs.org/cgi-bin/utree.pl The Unix Tree(可以看到很多老系统的源代码) [8] https://zh.wikipedia.org/wiki/丹尼斯·里奇

用户评论

江山策

哇,万字详解,真是厉害!一直想了解C语言的起源和发展,这篇博文满足了我的好奇心。

    有20位网友表示赞同!

拽年很骚

看了这篇万字长文,对C语言的了解深了不少,感觉作者真的下了一番苦功。

    有9位网友表示赞同!

来瓶年的冰泉

好长的一篇文章啊,但是作者讲解得非常清晰,对C语言的热爱让我也有了继续学习的动力。

    有11位网友表示赞同!

百合的盛世恋

虽然篇幅很长,但我硬着头皮看完了,收获颇丰,感谢作者分享。

    有9位网友表示赞同!

剑已封鞘

读完这篇C语言发展史,感觉自己像个小学生,不过作者用词准确,细节丰富,值得一看。

    有9位网友表示赞同!

我一个人

看了这篇文章,我对C语言的敬意又深了一层,感觉这是编程界的传奇语言。

    有10位网友表示赞同!

全网暗恋者

没想到C语言的历史这么丰富,作者真是用心良苦,希望今后能多看到这样的文章。

    有18位网友表示赞同!

tina

这篇万字长文虽然内容详实,但读起来有些枯燥,希望作者能在叙述上再下功夫。

    有17位网友表示赞同!

浅嫣婉语

作为一个C语言新手,这篇文章对我来说太有用了,特别是那些细节,让我对C语言有了更深的认识。

    有17位网友表示赞同!

巷雨优美回忆

看了这么多关于C语言的文章,这篇是最全面的,特别是那些历史细节,让我对C语言有了全新的认识。

    有17位网友表示赞同!

玩味

感觉作者对C语言的历史了如指掌,不过有些地方我觉得可以更加深入浅出。

    有5位网友表示赞同!

荒野情趣

文章太长了,中间有几处感觉有些重复,不过总体来说,对C语言的发展史有了更全面的认识。

    有5位网友表示赞同!

如梦初醒

作为一个老程序员,看到C语言的发展史,不禁感叹时光荏苒,感谢作者让我们重温这段历史。

    有5位网友表示赞同!

秒淘你心窝

虽然篇幅很长,但我觉得作者对C语言的热爱感染了我,让我有了重新学习C语言的冲动。

    有8位网友表示赞同!

独角戏°

这篇文章让我对C语言的起源和发展有了更深的了解,特别是那些技术细节,让我受益匪浅。

    有7位网友表示赞同!

莫阑珊

读完这篇文章,我对C语言的发展史有了全新的认识,感觉作者真的用心去做这个专题。

    有12位网友表示赞同!

心安i

万字长文,确实让人望而生畏,但作者通过丰富的案例和生动的叙述,让文章变得生动有趣。

    有14位网友表示赞同!

无寒

感谢作者分享这篇C语言发展史,让我对这门语言有了更深的感情,也让我更加热爱编程。

    有19位网友表示赞同!

迷路的男人

这篇长文让我对C语言的历史有了更全面的认识,特别是那些技术细节,让我对编程有了更深的敬畏之心。

    有5位网友表示赞同!

不识爱人心

作为一个C语言爱好者,这篇文章让我更加坚定了学习C语言的决心,感谢作者的辛勤付出。

    有16位网友表示赞同!