读谭师傅的书(9) 读谭师傅的书(11)
Mar 31

前面已经学习过第三章3.5节《字符型数据》,现在学习3.6节《变量赋初值》。

1、谭师傅说,“C语言允许在定义变量的同时使变量初始化“。又把“声明”当了“定义”。

2、谭师傅还说,“也可以使被定义的变量的一部分赋初值”。如果不看后面的例子,估计谁也不明白谭师傅讲的“变量的一部分”是什么部分。原来,谭师傅的意思是,“int a, b, c=5”这样的语句只对变量 c 赋初值。原来这就叫做“变量的一部分”啊。

3、谭师傅又教导我们说,“静态储存变量和外部变量的初始化是在编译阶段完成的”。谭师傅的“谭氏编译器”真是牛到不行了,程序还没运行就能初始化变量了。

接下来是第3.7节《各类数值型数据间的混合运算》。

4、谭师傅在讲什么是“数值型数据”时讲了整型、浮点型、字符型,漏了枚举型。本来嘛,按K&R,所有这些都叫做“算术类型”,不就很清楚了吗?按“谭氏分类法”,连谭师傅自己也不免考虑不周。

5、 谭师傅教导我们说,“float型数据在运算时一律先转换成双精度型,以提高运算精度”。不幸的是,前半句只对ANSI C之前的K&R C成立。在标准C中,两个float做算术运算时已经不会再转换成double。而后半句则完全是错的。K&R C里做了这样的转换只不过是因为当时Unix运行的硬件上有内置的双精度型,所以用双精度型反而比单精度型要快。与此类似的是char和short在表达 式中自动转成int。都是因为提高速度而不是提高精度。

接下来是第3.8节《算术运算符和算术表达式》。

6、谭师傅把运算符分了很多类,看起来是按运算符的“功能”分的,着实下了一番工夫。不过,C运算符的真正重要之处,即优先级和结合性,谭师傅没有仔细讲,只教人去看附录。有几个学生读课本时会去仔细研究附录?

7、谭师傅把做为负号的-和作为减法的-当成了同一个运算符来讲,实在是不应该。

8、谭师傅说,“如果参加+、-、*、/运算的两个数中有一个实数或双精度数,则结果是double型,因为所有实数都按double型进行运算”。看了 这句话,让我以为谭师傅在讲Fortran还是什么的,反正不是C。因为C语言里没有“实数”这个类型,也没有什么“所有实数都按double型进行运算 ”的规则。如果说C的“实数”是指所有可做算术运算,又非整数的数,那么它就应该包括“long double”,其精度不会比double低,因此在运算时如果有一个是long double,结果也是long double。

9、谭师傅在谈到“强制类型转换”时说,“在强制类型转换时,得到一个所需类型的中间变量”。这个“中间变量”不知道是什么神奇的东西。课后思考题:中间变量是变量吗?

好了,今天就学到这里,下次再学

“读谭师傅的书(10)”有8篇评论

  1. ronaldfree Says:

    希望这个系列不要停。唉,以前被谭师傅害死了。当时以为谭是个很厉害的人,因为很多大学都是用他编的教材,所以我自学C语言想都没想就用了他的C语言的教材。谭师傅真是害人不浅啊!

  2. bonntom Says:

    3、谭师傅又教导我们说,“静态储存变量和外部变量的初始化是在编译阶段完成的”。谭师傅的“谭氏编译器”真是牛到不行了,程序还没运行就能初始化变量了。
    这里的真实意思应该是,这些变量的值在编译阶段就已经决定了。这些值能在可执行文件中找到的。



    回复:写教科书应该尽量做到语言的精确。如果教科书时还得不时想着“这里真实意思是什么”,那还不如不要读。更何况就算按你改的也不全对,因为外部变量的初始化通常都不是在用extern的那个文件里,而是它作为全局变量被声明/定义的地方。

  3. bonntom Says:

    9、谭师傅在谈到“强制类型转换”时说,“在强制类型转换时,得到一个所需类型的中间变量”。这个“中间变量”不知道是什么神奇的东西。课后思考题:中间变量是变量吗?

    看一个简单的例子:
    double a=(double)b;
    右边运算时,会生成一个double类型的变量,我们可以称为c,这个c的值随后就赋给a,然后这个c值所占的内存就会释放。基于此,c就称为临时变量



    回复:变量的特征是可以做左值。(double)b产生的只是一个值,不是一个变量。

  4. ct Says:

    “C语言允许在定义变量的同时使变量初始化”没错。例如:
    如果函数体外出现extern int n=1; 或 int n=1; 则是“定义”全局变量n,同时将其“初始化”。
    如果函数体外出现extern int n; 则是“声明”全局变量n,此变量在他处(例如另一个源文件中)“定义”。
    如果函数体外出现两处 extern int n=1; 或 int n=1; 则重复定义。



    回复:书里在讲到这里时,用的例子都是在讲“声明”时可以同时初始化。

  5. ct Says:

    看来是谭师傅搞不明白“声明”和“定义”的区别:)
    谭师傅终于整对了一次,应该鼓励才是。

  6. bonntom Says:

    我的意思是,全局变量的值应该在编译期决定,这个值你可以在生成的机器代码看得出来。而不是像一般的变量,是在运行时赋值的。至于全局变量在哪个文件初始化(当然你的解释是对的),在机器码中不存在这个问题。谭师傅的书的毛病是没有结合最终生成的机器码进行讨论,所以不明不白。另外那个临时变量的问题,你说得对,从语义上它确实只是右值,不能称之为变量。不过我觉得这里的重点是要告诉读者,转型操作会有一个额外的内存分配过程,而不是像直观理解那样的。

  7. 穆扬 Says:

    “float型数据在运算时一律先转换成双精度型,以提高运算精度”
    这个谬误流传甚广

  8. 穆扬 Says:

    害人无数

发表评论

CAPTCHA Image
*