C语言概述
C语言的历史
C诞生于上个世纪70年代初的贝尔实验室,由Ken Thompson和Dennis Ritchie设计开发出来的,目的是为了重写UNIX操作系统。

也可以说C语言是UNIX系统的“副产品”。
C语言不是凭空创作出来的,而是诞生于一个演化过程。

Ken在贝尔实验室在一台DEC PDP-7机器上,使用改进后的BCPL语言,也就是B语言,设计开发了初版的UNIX系统。
BCPL语言源自ALGOL60,也就是算法语言,它长得样子大概是这样:
BEGIN
FILE F(KIND=REMOTE);
EBCDIC ARRAY E[0:11];
REPLACE E BY "HELLO WORLD!";
WRITE(F, *, E);
END
可以看到函数WRITE
的方法调用,;
结尾的语句。当然它已经具备了IF
选择,FOR
循环等高级语言的特性了。
BCPL语言更近一步,它是Basic Combined Programming Language的缩写,可以看到它的样子:
GET "libhdr"
LET start() = VALOF
{
FOR i = 1 TO 5
DO writef("fact(%n) = %i4*n", i, fact(i))
RESULTIS 0
}
AND fact(n) = n=0 -> 1, n*fact(n-1)
BCPL有主函数start()
,有获取外部库函数的GET
指令,同时有格式化输出函数writef
,看起来已经很有感觉了。
Ken所作业的DEC PDP-7不是一个很强的系统,只有4K的内存。

Ken发明的B语言。
/* The following function will print a non-negative number, n, to
the base b, where 2<=b<=10, This routine uses the fact that
in the ANSCII character set, the digits 0 to 9 have sequential
code values. */
printn(n,b) {
extrn putchar;
auto a;
if(a=n/b) /* assignment, not test for equality */
printn(a, b); /* recursive */
putchar(n%b + '0');
可以看到已经和C很像了,这个时候Dennis加入了项目组,同时他们更换了一台性能强劲的新机器DEC PDP-11。

由于B不能很好的利用新机器的特性,比如一些新的指令集,因此Dennis的主要工作就是给B打patch。可是patch打到最后导致B已经不再像原有的B了,Dennis就索性推翻了重干,操刀设计出了C,并用它和Ken一起重写了UNIX。
那个年代的程序员就像刀客:荒漠里一酒家,满屋皆是恶人。外来一人执刀,躬身不惧而入,刀光闪剑影舞。独他推门而出,收刀带帽上马。马踏夕阳西下,只留无人酒家。
任何软件的目的,都是为了驱动硬件。和硬件交互最深入的软件,就是操作系统。

在Java语言中,RUNTIME(JVM)针对不同的操作系统做了不同的实现,但是它们需要兑现一个目标,为上层代码(Java代码)提供一致的标准,也就是Java Spec。可以看到很多语言及功能的特性,诸如:网络、文件和线程等,都抽象到了Java Spec中,Java开发者可以在SDK中看到这些内容,而它们需要得到RUNTIME的支持与兑现。Java应用和程序都是基于Java Spec的,而整个Java实际上就是一个平台。
在C语言中,不同的操作系统提供各自对应的编译器,而C只是定义了C Spec,具体编译和链接就需要依靠不同操作系统上的编译器。这也是C编译器在不同操作系统(如:Windows或Linux)迥异的原因了。
C语言的优缺点
C语言的优缺点。

Java的语言特性比较多,并且在不断的增加,而C只能依靠标准库,如果没有标准库,那么移植性就存在问题。
同时C的编译器能力不强,有些隐藏错误难以发现。所以对于C需要注意。

针对下面的代码。
#include<stdio.h>
void main() {
printf("hello, world!\n");
}
尝试使用gcc进行编译。
ch02 % gcc -o target/warn warn.c
warn.c:3:1: warning: return type of 'main' is not 'int' [-Wmain-return-type]
void main() {
^
warn.c:3:1: note: change return type to 'int'
void main() {
^~~~
int
1 warning generated.
编译结果出现告警。然后使用新的命令再次编译。
ch02 % gcc -O -Wall -W -pedantic -std=c99 -o target/warn warn.c
warn.c:3:1: error: 'main' must return 'int'
void main() {
^~~~
int
1 error generated.
编译失败,只是因为增加了-std=c99
,也就是说要求编译前按照c99的标准检查代码,而对于主函数返回类型,c99要求必须为int
,所以直接报错。通过增加-Wall -W
,也能够看到告警,这样会让我们知道哪里可能存在风险。