May 27

接着上次的学习。之前在读谭师傅的书时,有的地方跳过去了。现在重新回过头来看看第四章,《最简单的C程序设计--顺序程序设计》。

第4.1节是《C语句概述》。我们来看看谭师傅的图4.1。

figure4-1

 

 

 

 

在这里我们可以很清楚的看到,这里少了点东西:函数声明。如果一个文件有函数声明,但没有该函数的函数体,则按这个图,这个文件不是C程序。再严格一点,这里还少了注释、typedef的位置。

谭师傅在讲解的时候说,“一个C程序可以由若干个函数和预处理命令以及全局变量声明部分组成”。这问题就更大了。如果我有一个 struct foo { int bar; } ,可能还可以勉强算是“数据声明”,但决不是全局变量的声明。静态变量的声明也没有包括在里面。

谭师傅接下来把C 语句分为5类,分别是(1)控制语句、(2)函数调用语句、(3)表达式语句、(4)空语句,以及(5)复合语句。这种分类方法和通常使用的分类方法(即 C标准中使用的分类方法)不同,很可能会造成初学者的误解。例如,谭师傅说,if()…else…这样语句的小括号里的内容是一个“判别条件”。 这个判别条件是个什么东西?它是不是一个语句?谭师傅没有讲。其实,它就是一个表达式,而且对它的返回值有一定要求(必须是scalar type)。按谭师傅的说法,for()… 的小括号里也是一个“判定条件”。这个判定条件是什么东西?它是三个用分号隔开的表达式(或按最新的标准草案,可以是一个声明加两个用分号隔开的表达式)。另外,函数调用也是表达式(这点谭师傅自己也提到了)。空语句其实也是表达式语句,理解了这点才能知道为什么可以写出 for(;;)… 这样的语句。我不明白谭师傅在搞出这么一个不伦不类的“分类”的时候有没有好好读过K&R或者C标准。

第4.3节讲的C语言的输入输出。谭师傅讲了什么是头文件:“文件后缀中‘h’是head的缩写,#include命令都是放在程序的开头,因此这类文件都被称为‘头文件’。” 这里有点小问题,h应当是header而不是head的缩写。

谭师傅还说,在包含stdio.h的时候,既可以用 #include <stdio.h>,也可以用 #include “stdio.h” 的形式,但却没有讲两者的区别。这是初学者比较容易搞混的地方,不该放过。事实上,对于编译系统提供的头文件,用第一种形式比较好。

第4.4节给了几个例子。我们又一次看到谭师傅把字符常量的类型当成了char,把getchar()的返回类型也当成了char。而实际上这两者都是 int。

第4.5节在(12)里已经学习过了,这里就不多说了。

Mar 20

看了新到中这篇文章之后很是诧异。短短三段话,错误一大堆。以下是我的评论:

1、C和C#是两个完全不同的语言。除了语法看起来有点像之外,没有任何可比性。谭的书可是讲的C语言,勉强把C++拿来说说也罢,C#是怎么冒出来的?

2、1999年的C标准(实际上是ISO C而不是ANSI C,通常称之为C99)实际上是C语言“最新”的标准,而不是什么“古老的东西”。而且在网上最多只能找到这个标准的草稿。毕竟人家ISO要拿来卖的。

3、事实上,最容易获得的是C89。这是因为C89已经包含在C语言的“圣经”,K&R第二版里面了。这本书就算是正版价格也不贵,相信张云楼老师还是买得起的。

4、目前C标准只有三个版本,C89、C90以及C99。没有哪一个标准允许switch带非整数参数(注意是整数不是整型)。不管是什么标准,找个C编译器(如谭师傅推荐的古董TC)试试不就好了?最好的莫过gcc,因为用它编译时可以指定用哪一版本的标准。

5、从g3like列出的C#中switch可以接受的类型来看,除了string,其它也都可以表达为整数。如果可以相信这个列表是完整的,那么就算是在C#里switch也不能接受“任何类型”吧?“也许是正确的”这样的诊断从何而来?

6、 实事上,C语言的switch可以接受的类型除了整型、字符型和枚举型以外,还包括短整型、长整型、长长整型,以及所有这些的有符号和无符号的类型。也就 是说,g3like列出的C#接受类型中,只有string是C语言里没有的类型以外,其它的相对应的C类型都可以被C语言的switch接受。

7、C++里面的switch也同样不能接受整数类型以外的类型。