>第 21 章 预处理>宏定义>内联函数

范一璠 luomojingyun@qq.com
2009-10-30 19:35:39

宋老师你好:
    今天偶然看到有人推荐你的书,下载下来大致看了下,果然是好书,非常感谢。
    只是今天我查找关于c语言内联函数的时候,在函数那个章节没找到,后来在宏定义那个章节找到了。感觉内联函数毕竟还是函数,跟宏不同,所以还是放在函数部分,然后在预处理这里再提及一下为好。
    如果提的不对,还请见谅。^_^


宋劲杉 songjinshan@akaedu.org
2010-01-21 16:04:26

为了便于比较inline函数和函数式宏定义,我认为还是应该把它们放在同一章中


LN pmerofc@126.com
2010-01-26 00:00:13

C语言规定这些重复的宏定义必须一模一样。

介绍这条规则有意义么?
什么时候会这样写?


宋劲杉 songjinshan@gmail.com
2010-03-02 20:46:03

一种典型的情况是:一个文件包含另一个文件,一个宏定义在两个文件中分别定义了。
即使在同一个文件中定义两次也不稀奇。
“介绍这条规则有意义么?什么时候会这样写?”这是你看书时应该问自己的问题,而不是问我的问题。


LN pmerofc@126.com
2010-03-28 09:58:52

“一个文件包含另一个文件,一个宏定义在两个文件中分别定义了。”
这本身就是应该极力避免的东西,而且有相应的措施。你这样写,在我看来,和老谭写“#include "file.c"”没什么区别。
顺便说一句,我根本不是在问你问题。


宋劲杉 songjinshan@gmail.com
2010-03-28 15:02:12

第一,我没有在任何示例代码中采用这种写法
第二,我没有推荐或建议这种写法,本书其它地方有很多语法我虽然讲到了,但同时也都加上一句“不推荐这么写”

综上,怎么能把我和老谭的#include "file.c"相提并论呢?

如果说我讲了这个语法是我的错,那么我的错误在于虽然没推荐这么写,但也没明确说“不推荐这么写”。也许我应该说“在维护legacy code和vendor code时要注意你可能重定义了他们code里已经定义过的宏,但你自己写代码不应该依赖这个语法特性”,但我隐约觉得这么说过于武断了。

OK,这既然是个问题,我一定去把它的rationale查清楚,等下一版时给你一个满意的答复。


LN pmerofc@126.com
2010-03-28 19:23:13

Use the good features of a language;avoid the bad ones.
我认为
既然是写给初学者的
讲这个语法都没必要
因为你写的不是手册或大全
写书不能只求把语法讲对
那样顶多比老谭强点
应该引导读者养成良好的习惯
供参考
  


宋劲杉 songjinshan@gmail.com
2010-03-28 23:42:35

“应该引导读者养成良好的习惯”我完全同意,本书已经在这方面做了很多努力。当然也有不尽人意的地方,这里也需要再改改。

但另一方面,我写这本书确实是希望把语法讲得全面一些。别的C语言书都不会像表15.3那样讲类型转换的规则细节,但我要讲,别的C语言书都不会像表20.1那样讲extern和static,但我也要讲。为什么呢?因为C语言和Java不一样,用Java再怎么乱搞顶多出个Exception,而且出错原因汇报得很清楚,而用C语言乱搞的后果很严重,原因也很难弄清楚,即使自己不乱搞,维护别人乱搞的代码也会面临同样的困难。如果这些问题都搞不定,那学完了C语言根本不能胜任开发工作,还学C语言干吗?

本书是面向零基础的读者(我承认这一点还没完全做到,还需努力),但我并不希望读者看完这本书之后还是个初学者的水平。如果市面上所有的C语言书都只是帮初学者入门的,那到底该看什么书才能进阶?


宋劲杉 songjinshan@gmail.com
2010-03-28 23:55:34

当然,语法大全类的也有C The Complete Reference这样的书,这种书都晦涩难懂,只有熟悉C标准的人才知道它在说什么,但熟悉C标准的人真的需要看这种书吗?

一边是C语言基础书,各种概念、定义都很含糊,一边是C标准的解说版,怎么去填补中间的鸿沟?这正是我想做的,我可不想做“Yet another C语言基础书”。

总之,本书下一版可能还会把更多语法特性添进来,而不会删掉现在讲过的任何语法。


LN pmerofc@126.com
2010-03-29 00:33:00

“而不会删掉现在讲过的任何语法”
这个很难赞成
我觉得有些东西是应该回避的
比如
{
  int i ;
   {
    int i;
    ……
   }
  ……
 }
这种东西
只有老谭那种自己都不懂C的作者才会津津乐道
只有那种狗屁不通的等级考试才成天考个没完
有教养的程序员会装做不知道有这回事

再说,语法是讲不完的
要是面面俱到
那个CAST运算没有两章都讲不完(你的表 15.3只有算术类型的)
表 15.3在我看来并不成功
好的程序员谁会成天转换类型?

你的书我翻过(个别章节)
总的来说感觉还不错(比如自然语言和形式语言那节就很精彩)
在国内的C语言书里也算翘楚了
不过希望能更完美些
也许是爱之深,责之切吧
希望不要介意


LN pmerofc@126.com
2010-03-29 00:40:50

表 20.1. 
我也不看好

C的外部变量的声明和定义是很乱的
这并不是C的优点(当然你做了努力的归纳)
应该遵循简单易用的原则
找一种最值得推荐给学员的使用模式
而那种很烂的使用方式
又何必介绍呢
你希望他们那样写?



LN pmerofc@126.com
2010-03-29 00:49:28

“那到底该看什么书才能进阶?”

这个想法是很好的
但你的书的内容决定了你很难实现你的目标
因为你加深的不仅仅是C
还增加了数据结构、操作系统、汇编、网络编程……

“面向零基础的读者”
难啊


宋劲杉 songjinshan@gmail.com
2010-03-29 10:46:43

自然语言和形式语言那节我倒不觉得很有意思,只是为了交代必要的前提,必须写在那里罢了。

看起来你还是很学院派的,不喜欢ugly的东西,如果在实际工作中维护过legacy code和vendor code肯定就不这么想了。

C语言是充满陷阱的,唯有把一切规则都了然于胸才能顺利淌过去,自己写代码不犯规并不能阻止你维护的代码犯规。而且我强调过,一旦出了问题,C语言比Java难除错得多,一个类型转换不当,无声无息地就能搞死你。

除非你坚持别人写的代码都是垃圾,拒绝维护别人的代码,一切代码都自己从头写起,那的确可以不必了解太多没用的语法规则。

表15.3只有算术类型的转换规则。那除了算术类型还有什么类型可以转换呢?非标量类型不能相互转换,那就只剩下指针类型了,指针就是个地址,没有复杂的转换规则,其实这些在书中其它地方也都讲到了。

关于定义和声明,你说应该“找一种最值得推荐给学员的使用模式”,而我正是这么做的,20.2.1和20.2.2节就是推荐的使用模式,20.2.3节和那个表是补充说明。本书在讲大部分这种语法细节时都会加上一句“不建议这么使用,但为了出错时能意识到这个地方可能会有问题,我还要是讲一讲”。

关于重复定义同一个宏的语法细节,我目前还不敢断定它一定是没用的,所以没有加上“不建议这么使用”的字眼,我还需要研究一下其它程序员使用宏定义的Paradigm,回头再改改。算是我在这里打了个马虎眼,被你发现了吧。

{
  int i ;
   {
    int i;
    ……
   }
  ……
 }
你不喜欢这种题目,我认为是一种逆反心理。二级考试虽然很垃圾,但不能说“凡是二级考试涉及的内容都是垃圾”。做出任何一个结论都需要严谨的论证。从这个角度看你又不是真正的学院派,而是批判式的学院派。

即使写出这种代码真的absolutely被认为是垃圾代码,任何人都没有维护这种垃圾代码的风险,即使是这样,学习这个语法从研究Programming Language这门学科的角度来看也是有意义的,它教会了我们什么是Scope,更进一步,有些编程语言还有Lexical Scope和Dynamic Scope之分。



宋劲杉 songjinshan@gmail.com
2010-03-29 10:55:32

又要面向零基础的读者,又要带他们进阶,是挺难的,我承认现在并没有做好,本书的第一部分是面向零基础读者,后面两部分是进阶,主要是第一部分做得还不够好,因为我毕竟不是零基础了,有些时候我真想不到零基础的人会怎么想。所以我正在努力找零基础的人帮我review这本书。

但这本书就是为这个目的而写的,是为IT职业教育写的。如果被证明这是不可能的,那也就证明了职业教育是不可能的,所有职业教育都是骗人的把戏。我到现在为止没有看到真正成功的职业教育,我自己也已经离开了IT培训行业,但也不能证明这是不可能的。

总之,这本书哪里讲得不够详细,我就再讲详细些,大的方向不能变。我还是希望证明IT职业教育是可以做好的,我有一天还会回到这个行业。


LN pmerofc@126.com
2010-03-30 01:19:19

“C语言是充满陷阱的,唯有把一切规则都了然于胸才能顺利淌过去”

恐怕没什么人能作到这点(除了Guy l.Steele Jr.这样的少数人)
更不要说你的学生了
其实任何语言都不可能完美
是绕过陷阱,漂亮地拿出代码
还是每个陷阱里都去折腾一番
看起来这是个哲学问题
哲学问题是不好讨论的
每个人都有自己的信念

至于IT职业教育
这是个更大的话题
不是一本书能解决的
但我觉得
职业教育的前提是行业发展健全到一定程度才有可能
因为那时才会有分工
有分工才能把教的内容变窄
教的内容变窄,职业教育的路才会更宽
职业教育不是教全才、通才的



LN pmerofc@126.com
2010-03-30 01:24:02

我的确不喜欢ugly的东西
但我不知道什么是学院派
所以也不好承认或否认
如果你认为我是美学派的
我想我会承认的
在我看来
老谭是C语言“丑学派”的领军人物之一


LN pmerofc@126.com
2010-03-30 01:28:35

自然语言和形式语言那节
是绝大多数书中没有的
事实上多数初学者一开始意识不到它们之间的区别 
部分人要过很久才能慢慢悟出来
有的人则一辈子也悟不出来
所以一开始指出形式语言的特点
很有意义


LN pmerofc@126.com
2010-03-30 01:34:29

你说“如果市面上所有的C语言书都只是帮初学者入门的,那到底该看什么书才能进阶?”

其实可以看的国产C语言书不超过5本
我可以把你的书算做之一
不过是“进阶”的
但基础没打好
你让你的学生们怎么进阶?



宋劲杉 songjinshan@gmail.com
2010-03-30 10:38:09

“但基础没打好,你让你的学生们怎么进阶?”

那怎么才能打好基础呢?假如说照本书的第一部分那样教还不够,那还需要教些什么?我需要的是有建设性的意见!

如果你有什么好的方法,我十分欢迎。哪里讲得不到位我再多讲讲就是了。我是希望这本书是“基础+进阶”,所以你不要把我的书直接定位成“进阶”,然后再质问“基础都没打好,怎么进阶”。只是抱怨、牢骚而没有建设性的意见,是没有用的。

“是绕过陷阱,漂亮地拿出代码,还是每个陷阱里都去折腾一番”

你还是没明白我的意思,自己写代码当然要“绕过陷阱,漂亮地拿出代码”,但维护别人的代码你就说不算了,别人已经掉陷阱里了,而你没有选择必须维护他的代码,那只能去陷阱里折腾一番。还有一种情况是你维护的代码很漂亮,你自己写的代码也很漂亮,但你们写代码的习惯不一样,导致接口上出现陷阱,也是绕不过去的。最后,即使代码写得再漂亮,也会有粗心留下Bug的时候,而除错时同样需要对各种陷阱有充分的把握。

“教的内容变窄,职业教育的路才会更宽,职业教育不是教全才、通才的”

对于汽修培训也许是这样。对于IT培训,这个观点我不能认同。比如,不了解虚拟机的底层工作原理是写不出好的Java程序的,Joel Sposky也这么认为。



LN pmerofc@126.com
2010-03-30 11:35:24

这话应该两说
第一,我认为你想达到的目的是不可能实现的任务(4个月)
当然,职业教育都喜欢大言炎炎,这我理解也不反对,但广告就是广告,不能当真事儿的
所以就你的目标而言我是绝对不打算掺和的
也不会提任何“建设性”的意见
第二,我注意到了你的书其实是下了不少工夫的
我翻看过部分内容
我认为“自然语言”那部分很好
此外把数据在纸上画成不同形状的图形也是很好的创意
此外你的书对概念的讲解还是比较认真准确的
比5本之外那些书强过不知多少
这是我比较赞赏的地方
也就是说
你的目标我认为不可能
但你努力带来的SIDE EFFECT还是不错的
你的书是有价值的
但能否达到你希望的效果
恐怕还得不看广告看疗效

“Joel Sposky也这么认为”
当然不错
但问题在于这种人才是否适合用职业教育的方式培养
严格地说
优秀的汽修工应该懂得材料力学和机械原理
但培训是不讲这些的
这些可以留在终身教育中完成
然而目前的IT职业没有类似的映射
四个月
培养专门写某一专业领域代码的工人是足够的
但是那种全面的人才是培养不出来的

“只是抱怨、牢骚而没有建设性的意见”
你这样讲是不公正的
实际上我的意见很清楚
不要讲多数情况下正常编程没有用的东西
更不要讲风格不好的语法
象类型转换那种烦琐的教条
应该让学员知道这里应该小心
在编程时有能力查阅手册就可以了

就我个人而言
是不“维护别人的代码”的
更不要说维护别人ugly的代码了
我自己的代码也是重写的情况较多
代码底子不好,任何高手也没办法把它改好
这是常识
那么就引出了一个问题
IT教育是否应该向现存的ugly妥协让步也把自己变得ugly
还是应该向学生灌输先进的美的理念,洁身自好
这看来也是个哲学问题
我只知道你我的答案是不一样的


LN pmerofc@126.com
2010-03-30 11:45:13

我有点感到暗暗吃惊的是
似乎你只把“纠正一个错别字”当作“建设性意见”
其实在软件开发中
最重要的是需求分析吧
但愿这只是我的错觉


宋劲杉 songjinshan@gmail.com
2010-03-30 12:54:54

我不知道我为啥这么有耐心回你的帖 -_-

我说“请提建设性意见”,只是针对你的“基础都没打好,如何进阶”这句话而言。我的意思只包含“关于如何打好基础请提建设性意见”,并非认为你提的其它意见都没有意义。我是不同意删去一些细节的讲解,但我同意加上一些提示,“这些语法不建议用,只在除错时也许用得着”。

比如类型转换的规则,你说用到的时候查手册,可是我都不知道该查什么手册,别的书上都没有这样总结出来,我参考的那本书有一个类似的表格但有不少地方和C99不一致,直接查C99又太低效率了,所以我把它整理出来就是为了方便大家用到的时候查啊。

关于“是否应该向现存的ugly妥协让步也把自己变得ugly”,答案是肯定的。如果不必妥协,C标准也不会是现在这个样子了,以前的很多语法明知道是ugly的但都被保留了下来。事实上,很多高手写的代码并不美观,有些人还故意写出难懂的代码也显示自己NB。ffmpeg、nginx里面大段大段乱七八糟的代码,但大家都在用它,维护它。没办法,自己不够NB能在很短的时间内重写一个,就只有将就用了。

关于职业教育,这只是我的一个理想,我说了,现实是没有人已经做得很好了。我想做,但也许这是个错误的方向,把我一辈子就搭进去了。但你说得对,即使这是个错误的方向,也会产生side effect就是出来几本真正像样的书,那也算没白做了。


LN pmerofc@126.com
2010-03-30 19:50:50

既然您是在耐着性子回贴
那就算我多嘴吧
我收回前面说过的话
少陪


goophile goophile@gmail.com
2010-08-15 12:04:57

“其实可以看的国产C语言书不超过5本”,好奇,是哪5本?


如果您有建设性意见,哪怕只是纠正一个错别字,也请不吝赐教,您留下的姓名和email将会出现在本书前言的致谢中。再次感谢您的宝贵意见!