• 回头望C

    版权声明:转载时请以超链接形式标明文章原始出处和作者信息及本声明
    http://dreamhead.blogbus.com/logs/32787473.html

    周游了许多语言之后,重回C的怀抱,那些之前不曾注意的问题,浮出了水面。

    从头文件说起,第一个问题就是为什么要分头文件,也许最恰当的答案就是编译器技术受限C产生那个年代的资源。

    还记得刚开始学写C程序的时侯,第一次学会防止重编译的手段觉得自己很厉害,开始向专业人士迈进了:
    #ifndef _BLAH_H
    #define _BLAH_H

    ...

    #endif

    虽然这样的代码让自己看上去更像真正的C程序员,可除了C/C++,我再也没有用到过这种手法。原因很简单,其它语言都有自己的处理方法,确保消除这种重复。比如Ruby里面的require,会由运行时系统检查该文件是否已经包含其中(虽然做得并不完美)。仔细想想,其实,即便是C,如果改进一下编译器,比如加上一个包含文件的列表,就完全可以做到这一点。还是前面提到的那一点,那个年代的编译器技术遗留下的问题,把原本该由编译器做好的事情,留给了程序员。幸运的是,这种防止重编译的手法已经成了事实的标准。

    接下来的问题是头文件里面放什么?通常的说法是放声明。声明包括宏的声明、类型声明、函数声明,还有变量声明。是的,变量。从理论上说,头文件里面可以放任何东西,甚至是变量的定义(《大头随笔(一)》仔细讨论了声明和定义的差别)。

    从工程的角度出发,头文件扮演着接口的角色。也就是说,我们应该把一些一个模块允许其它模块调用的部份放在头文件里面。站在今天对软件开发的理解上,我们希望把数据隐藏起来,换句话说,变量不应该出现头文件。数据隐藏对于已经习惯面向对象的人来说,是一个基本常识,但是,很多还在编写C代码的人,他们总会告诉你,访问全局变量是一件多么惬意的事。看着说话时的幸福神情,我想他们多半是忘记了找bug的痛苦。

    当我们希望保护自己时,C语言却让我们显得是那么无能为力。尽管我们可以把头文件当作接口,但事实上,别人依然可以跨过不去理会头文件中的定义,直接访问模块内部定义的函数。很简单,声明一下就可以直接拿过来用,不仅仅是函数,变量也可以。而写出这种代码的原因通常是省事,而图一时之快的结果,对于工程来说,带来的只会是日后无尽的昏乱。也许只有混乱来临时,我们才会想起在C中还有一种叫做static的东西。

    由前面的讨论可以看出,C语言本身对于工程的支持还是很弱的,很多时侯,只能依靠约定,而虽然约定不是100%可靠,但聊胜于无。



    引用地址:

    评论

  • 当我们希望保护自己时,C语言却让我们显得是那么无能为力。尽管我们可以把头文件当作接口,但事实上,别人依然可以跨过接口,直接访问我们原本希望只有实现文件看到的代码。很简单,声明一下就可以直接拿过来用,不仅仅是函数,变量也可以。
    -------------------------------------------
    “希望只有实现文件看到的代码”可以使用static修饰,这样相应的函数或全局变量只能在当前的.c文件(确切地说应该叫编译单元)内可见。这样一来即使在其它的编译单元内声明了该函数/变量,也无法链接到static修饰的相应函数/变量。
    dreamhead回复kusk说:
    多谢指正,确实不够严谨。修改了一下。:)
    2008-12-21 23:57:34
::...
免责声明:
当前网页内容, 由 大妈 ZoomQuiet 使用工具: ScrapBook :: Firefox Extension 人工从互联网中收集并分享;
内容版权归原作者所有;
本人对内容的有效性/合法性不承担任何强制性责任.
若有不妥, 欢迎评注提醒:

或是邮件反馈可也:
askdama[AT]googlegroups.com


点击注册~> 获得 100$ 体验券: DigitalOcean Referral Badge

订阅 substack 体验古早写作:


关注公众号, 持续获得相关各种嗯哼:
zoomquiet


自怼圈/年度番新

DU22.4
关于 ~ DebugUself with DAMA ;-)
粤ICP备18025058号-1
公安备案号: 44049002000656 ...::