世间本无事,佣人自扰之

回到家了

01月 26th, 2005 by solarsea

     早上7点多起来,收拾好行李,吃了两块乐天巧克力派,看了一下时间,8点25了,出发。走到北太平桥下的十字路口的时候,来了一辆机场大巴,估计当时路上就我一个人背着包还拖着一个箱子,一看就是要坐大巴的,于是那辆大巴到站之后还等我慢慢得走过来。售票员说,小伙子还挺稳当啊,也不急,看你的样像要去机场的。我说,我怕赶过来要是还没赶上,在寻思是不是要坐下一班呢。差不多40分钟到了机场,果然来早了。去办手续的时候,托运了行李之后,小姐告诉我MF8116还没定从哪个登机口上,要不您过一会儿再来拿登机牌吧。靠,让我上哪儿玩去啊。在大厅里转了转,找了个位子等了半个多小时。 再过去了一次,小姐已经给准备好了登机牌,一看欧的序号是001,ft,果然来早了,是第一个办手续的。安检之后又等了半小时,才能登机,人还挺多的,中间给个老大爷让了座,rp++。

      上了飞机一看,这次的空姐质量还不错,也算没花冤枉钱,呵呵。午饭是米饭加虾仁和玉米,别的点心和以前没什么区别,然后要了杯咖啡。电视先放的是新闻,然后是很老的片子《杜十娘》,李嘉欣演的,以前没看过,结果声音实在太小,耳机音量开到最大都听不清,音效倒是有,就是说话听不清,结果就只能看着英文字幕了,还都能看懂,就是有些翻译实在太别扭,比如十娘居然译成lady ten,真够直接的,heihei。

       两点20到了长乐机场,等了10分钟才拿到行李。出来的时候,爸爸已经在等了,刚说了两句,看到妈妈在门口那边。妈妈晕车,所以以前坐飞机回来,都是爸爸一个人来接的,这回妈妈也来了,可见她又多想我。让妈妈担心了,真是罪过啊。好在是单位的车子,一路上开得不快,结果到家妈妈还是觉得不舒服,睡了一会儿。

       晚饭真是太爽了,好久没吃过这么多了,看得妈妈直乐,唯一不足是在北方呆久了,回来觉得菜怎么都没放盐似的,一点儿味儿也没有。福州的气温还算不错,今天最高20度,没觉得冷。

      回家的感觉真好。

Posted in 信手涂鸦 | No Comments

收拾收拾,准备回家

01月 25th, 2005 by solarsea

     明天中午的飞机,早上一起床就差不多得拿上行李到北太平庄做机场大巴了。昨天晚上去美廉美给家里买一大盒果脯,一盒茯苓夹饼,一盒十八街麻花,还有一只烤鸭,都是老妈要的,装到箱子里一看,差不多就已经满了,好在也没什么可带的。老妈交待不穿的衣服带回家,打开柜子看了看,没什么不穿的,有几件不要的,早就包好,准备捐了的,结果上回好不容易中午遇到一回,下午去就结束了,还是留到下次吧。寝室没有冰箱,烤鸭就扔在阳台了,反正气温也是零下,就当冰箱使了。
     早上popo走了以后,寝室就剩偶和monkey了,中午看完火箭的比赛,再去食堂一看,只有教工食堂开了两三个窗口,sigh,留在学校的人就指着它过年了,以教工食堂作出的食物的味道,真不晓得这些同学能否坚持得下来。
     来实验室最后检查了一下,硬件机器的电源是否关了,服务器是否关了,基本就没有什么别的任务了,晚上再最后洗个澡,就可以安心回家了。想想又快一年没回家了,去年2月7号到得学校,暑假因为中兴那个H264项目,也没放假,总算可以回去看看爸爸妈妈了。

Posted in 信手涂鸦 | No Comments

年前最后一天班

01月 21st, 2005 by solarsea

       今天是这学期最后一天班了,实验室已经有人提前回家了,也好,乐得清静。昨天在水木看到有导师询问年底给研究生发3000块年终奖金是否合适,觉得学生一年在外,也不容易,sigh,居然有这么够义的导师啊,即便平时会辛苦一些也值了,倒不是因为钱,有点儿人情味儿的导师,这年头也不多见了。
        最后一天基本就是整理一下机器里的资料,以便下学期使用,另外做一下备份。早上有火箭的比赛,用cool看了,结果一到投篮的时候就跳帧,ft,这还看个什么劲啊,只能看个比分,都怨CCTV不转播。不过好在最后赢了,也不枉坚持看了一场。看比赛的时候顺便看了一下c  programming  language中函数指针的部分,复习了一下。中午回去,看寝室一哥们兴高采烈的,一问原来拖了两个月的工资发了,而且一月份的也发了。俺们实验室倒是不拖欠,不过前天去查了,一月份的还没影儿呢,好在不是靠这些钱活着,有和没有也没太大区别了,本来也没干一个月活,不发也算有正当理由。
        小费明天的飞机回长沙,大家商量着年前一起吃顿饭,正好上回圣诞吃饭的券还没有花出去,只好再吃一顿火锅了。明后天考研,不知道还能不能到实验室来,今年居然有117w报名的,据说收60w,刚看的真情job版,到现在还有好多小硕没offer呢,国家还扩招,加上改成自费,国家饱饱得挣了一笔,学生们毕业喝西北风啊?Sigh,中国的教育越来越中看不中用了,高中的时候,老师说上了大学就好了,大学四年一混就过了,接着读研,好多人还是啥也不会就毕业了,再有读完博士的,一样找不到工作,心态还调整不回来,留校当老师,接着耽误下一代,这个独木桥,啥时候是个头啊。 胡乱发了一堆牢骚,呵呵,发泄一下对中国教育制度的不满,也没什么用,过完年还得好好干。

Posted in 校园拾贝, 毕业进行时 | No Comments

杂七杂八的事儿

01月 19th, 2005 by solarsea

     
早上学院搞了个什么信息工程学院第一届学术年会,选出了2004年发表的或者未发表的优秀学术论文,邀请作者作报告,上午是老师,下午是学生。李老师要求早上7点50到,结果没有睡好,一早上都没有精神。本来第一个安排的是周炯?院士的讲话,结果老先生最近血压比较高,来不了,信息就这么个宝,可经不起折腾,于是就取消了。后面钟义信和李道本教授一个讲了点儿全信息,一个讲了点儿LAS-CDMA,一个多小时就过去了。后边的基本是年轻老师,或者在读博士生,所以时间都不算长,主要内容有语音隐藏,金融汉字的手写识别,MIMO,H264中的ICT实现,Ad  hoc网络中TCP重传的研究,等等。一共有8个题目,听到第七个实在受不了了,看看周围好多人都已经走了,再说今早还有火箭队步行者的比赛,看了下表,已经11点10分了,于是悄悄溜了出来。吃了饭回寝室一看,靠,火箭又落后了10分,而且屡投不中,这个比赛还有什么意思啊。看了一会,徐济成也受不了了,说想吃饭的观众可以去打饭了,ft,可惜已经吃过了。忍着看完了火箭的比赛,最后还是输了10多分,郁闷。
     下午到实验室,还是很困,一点儿也看不进去东西。也不知怎么磨到了5点,收拾了一下,就去练跆拳道了。结果刚跑了会儿步,就觉得腿有点儿疼了,心想今天估计不妙。后来拉韧带的时候,时间比较长,拉完倒是挺爽,不过就是踢不了腿了。教练说就是要乘着疼的时候多踢,才能拉开,我晕,都疼得踢不了了呀。最后结束前还练了蹲踢,两趟下来,觉得腿都不是自己的了,倒是后边的俯卧撑还觉得轻松一些,不过也没往标准了做。完了以后,和教练借了平时训练时放的CD,主要是想放假回家自己练习的时候可以听听熟悉的音乐。最后到教工食堂吃饭,要了份羊肉泡馍,结果等了半天。回实验室的时候,师姐看到了,说怎么脸色这么不好啊, sigh,看来是自己太弱了。

Posted in 信手涂鸦 | No Comments

如何写makefile

01月 18th, 2005 by solarsea

在师兄留的文档里找到的,大多数内容在研究TriMedia的makefile时已经掌握了,但是还有一些用法不太清楚,看了一下,有些收获,转贴如下:

作者  ever (轩中圣主)                                      站内  GraduateSch

 标题  Re: [问题]makefile中可以用 用户自定义宏吗?

 时间  Tue Nov  4 19:44:12 2003

───────────────────────────────────────

看过这片, 基本的make应该都写的出来,当然这不是手册,太细节的函数以及

其他定义还是要自己查或man.

=================================

GNU make 指南

翻译: 哈少

译者按: 本文是一篇介绍 GNU Make 的文章,读完后读者应该基本掌握了

 make 的用法。而 make 是所有想在 Unix (当然也包括 Linux )系统上

编程的用户必须掌握的工具。如果你写的程序中没有用到 make ,则说明你

写的程序只是个人的练习程序,不具有任何实用的价值。也许这么说有点

儿偏激,但 make 实在是应该用在任何稍具规模的程序中的。希望本文可以

为中国的 Unix 编程初学者提供一点儿有用的资料。中国的 Linux 用户除

了学会安装红帽子以外, 实在应该尝试写一些有用的程序。个人想法,大

家参考。

—————————————————————–

—————

C-Scene 题目 #2

多文件项目和 GNU Make 工具

作者: 乔治富特 (Goerge Foot)

电子邮件: george.foot@merton.ox.ac.uk

Occupation: Student at Merton College, Oxford University, England

职业:学生,默尔顿学院,牛津城大学,英格兰

IRC匿名: gfoot

—————————————————————–

—————

拒绝承诺:作者对于任何因此而对任何事物造成的所有损害(你所拥有或不

 拥有的实际的,抽象的,或者虚拟的)。所有的损坏都是你自己的责任,

而 与我无关。

所有权: “多文件项目”部分属于作者的财产,版权归乔治富特1997

年 五月至七月。其它部分属 CScene 财产,版权 CScene 1997年,保

留所有 版权。本 CScene 文章的分发,部分或全部,应依照所有其它 CSc

ene 的文章 的条件来处理。

0) 介绍

~~~~~~~~~~~~~~~

本文将首先介绍为什么要将你的C源代码分离成几个合理的独立档案,什么

时 候需要分,怎么才能分的好。然后将会告诉你 GNU Make 怎样使你的编

译和连 接步骤自动化。对于其它 Make 工具的用户来说,虽然在用其它类

似工具时要 做适当的调整,本文的内容仍然是非常有用的。如果对你自己

的编程工具有怀 疑,可以实际的试一试,但请先阅读用户手册。

1) 多文件项目

~~~~~~~~~~~~~~~~~~~~~~

1.1为什么使用它们?

首先,多文件项目的好处在那里呢?

它们看起来把事情弄的复杂无比。又要 header 文件,又要 extern 声明,

而且如果需要查找一个文件,你要在更多的文件里搜索。

但其实我们有很有力的理由支持我们把一个项目分解成小块。当你改动一行

代码,编译器需要全部重新编译来生成一个新的可执行文件。但如果你的项

目是分开在几个小文件里,当你改动其中一个文件的时候,别的源文件的目

标文件(object files)已经存在,所以没有什么原因去重新编译它们。你所

需要做的只是重现编译被改动过的那个文件,然后重新连接所有的目标文件

罢了。在大型的项目中,这意味着从很长的(几分钟到几小时)重新编译缩

短为十几,二十几秒的简单调整。

只要通过基本的规划,将一个项目分解成多个小文件可使你更加容易的找到

一段代码。很简单,你根据代码的作用把你的代码分解到不同的文件里。当

你要看一段代码时,你可以准确的知道在那个文件中去寻找它。

从很多目标文件生成一个程序包 (Library)比从一个单一的大目标文件生成

要好的多。当然实际上这是否真是一个优势则是由你所用的系统来决定的。

但是当使用 gcc/ld (一个 GNU C 编译/连接器) 把一个程序包连接到一个

程序时,在连接的过程中,它会尝试不去连接没有使用到的部分。但它每次

只能从程序包中把一个完整的目标文件排除在外。因此如果你参考一个程序

包中某一个目标档中任何一个符号的话,那么这个目标文件整个都会被连接

进来。要是一个程序包被非常充分的分解了的话,那么经连接后,得到的可

执行文件会比从一个大目标文件组成的程序包连接得到的文件小得多。

又因为你的程序是很模块化的,文件之间的共享部分被减到最少,那就有很

多好处――可以很容易的追踪到臭虫,这些模块经常是可以用在其它的项目

里的,同时别人也可以更容易的理解你的一段代码是干 什么的。当然此外

还有许多别的好处……

1.2 何时分解你的项目

很明显,把任何东西都分解是不合理的。象“世界,你们好”这样的简单程

序根本就不能分,因为实在也没什么可分的。把用于测试用的小程序分解也

是没什么意思的。但一般来说,当分解项目有助于布局、发展和易读性的时

候,我都会采取它。在大多数的情况下,这都是适用的。(所谓“世界,你

们好”,既 ‘hello world’ ,只是一个介绍一种编程语言时惯用的范例程

序,它会在屏幕上显示一行 ‘hello world’ 。是最简单的程序。)

如果你需要开发一个相当大的项目,在开始前,应该考虑一下你将如何实现

它,并且生成几个文件(用适当的名字)来放你的代码。当然,在你的项目

开发的过程中,你可以建立新的文件,但如果你这么做的话,说明你可能改

变了当初的想法,你应该想想是否需要对整体结构也进行相应的调整。

对于中型的项目,你当然也可以采用上述技巧,但你也可以就那么开始输入

你的代码,当你的码多到难以管理的时候再把它们分解成不同的档案。但以

我的经验来说,开始时在脑子里形成一个大概的方案,并且尽量遵从它,或

在开发过程中,随着程序的需要而修改,会使开发变得更加容易。

1.3 怎样分解项目

先说明,这完全是我个人的意见,你可以(也许你真的会?)用别的方式来

做。这会触动到有关编码风格的问题,而大家从来就没有停止过在这个问题

上的争论。在这里我只是给出我自己喜欢的做法(同时也给出这么做的原因

):

i) 不要用一个 header 文件指向多个源码文件(例外:程序包 的 header

 文件)。用一个 header定义一个源码文件的方式 会更有效,也更容易查

寻。否则改变一个源文件的结构(并且 它的 header 文件)就必须重新编

译好几个文件。

ii) 如果可以的话,完全可以用超过一个的 header 文件来指向同 一个源

码文件。有时将不可公开调用的函数原型,类型定义 等等,从它们的C源

码文件中分离出来是非常有用的。使用一 个 header 文件装公开符号,用

另一个装私人符号意味着如果 你改变了这个源码文件的内部结构,你可以

只是重新编译它而 不需要重新编译那些使用它的公开 header 文件的其它

的源文 件。

iii) 不要在多个 header 文件中重复定义信息。 如果需要, 在其中一个

 header 文件里 #include 另一个,但 是不要重复输入相同的 header 信

息两次。原因是如果你以后改 变了这个信息,你只需要把它改变一次,不

用搜索并改变另外一 个重复的信息。

iv) 在每一个源码文件里, #include 那些声明了源码文件中的符 号的所

有 header 文件。这样一来,你在源码文件和 header 文件对某些函数做出

的矛盾声明可以比较容易的被编译器发现。

1.4 对于常见错误的注释

a) 定义符 (Identifier) 在源码文件中的矛盾:在C里,变量和函数的缺

 省状态是公用的。因此,任何C源码档案都可以引用存在于其它源 码档中

的通用 (global) 函数和通用变量,既使这个档案没有那个变 量或函数的

声明或原型。因此你必须保证在不同的两个档案里不能 用同一个符号名称

,否则会有连接错误或者在编译时会有警告。

一种避免这种错误的方法是在公用的符号前加上跟其所在源文件有 关的前

缀。比如:所有在 gfx.c 里的函数都加上前缀“gfx_”。如果 你很小心的

分解你的程序,使用有意义的函数名称,并且不是过分 使用通用变量,当

然这根本就不是问题。

要防止一个符号在它被定义的源文件以外被看到,可在它的定义前 加上关

键字“static”。这对只在一个档案内部使用,其它档案都 都不会用到的

简单函数是很有用的。

b) 多次定义的符号: header 档会被逐字的替换到你源文件里 #include

的位置的。因此,如果 header 档被 #include 到一个以上的源文件 里,

这个 header 档中所有的定义就会出现在每一个有关的源码文件 里。这会

使它们里的符号被定义一次以上,从而出现连接错误(见 上)。

解决方法: 不要在 header 档里定义变量。你只需要在 header 档里声明

它们然后在适当的C源码文件(应该 #include 那个 header 档的那个)里

定义它们(一次)。对于初学者来说,定义和声明是 很容易混淆的。声明

的作用是告诉编译器其所声明的符号应该存在, 并且要有所指定的类型。

但是,它并不会使编译器分配贮存空间。 而定义的做用是要求编译器分配

贮存空间。当做一个声明而不是做 定义的时候,在声明前放一个关键字“

extern”。

例如,我们有一个叫“counter”的变量,如果想让它成为公用的, 我们在

一个源码程序(只在一个里面)的开始定义它:“int counter;”,再在相

关的 header 档里声明它:“extern int counter;”。

函数原型里隐含着 extern 的意思,所以不需顾虑这个问题。

c) 重复定义,重复声明,矛盾类型:

请考虑如果在一个C源码文件中 #include 两个档 a.h 和 b.h, 而 a.h

又 #include 了 b.h 档(原因是 b.h 档定义了一些 a.h 需要的类型),

会发生什么事呢?这时该C源码文件 #include 了 b.h 两次。因此每一个

在 b.h 中的 #define 都发生了两次,每一 个声明发生了两次,等等。理

论上,因为它们是完全一样的拷贝, 所以应该不会有什么问题,但在实际

应用上,这是不符合C的语法 的,可能在编译时出现错误,或至少是警告

解决的方法是要确定每一个 header 档在任一个源码文件中只被包 含了一

次。我们一般是用预处理器来达到这个目的的。当我们进入 每一个 heade

r 档时,我们为这个 header 档 #define 一个巨集 指令。只有在这个巨集

指令没有被定义的前提下,我们才真正使用 该 header 档的主体。在实际

应用上,我们只要简单的把下面一段 码放在每一个 header 档的开始部分

#ifndef FILENAME_H

#define FILENAME_H

然后把下面一行码放在最后:

#endif

用 header 档的档名(大写的)代替上面的 FILENAME_H,用底线 代替档名

中的点。有些人喜欢在 #endif 加上注释来提醒他们这个 #endif 指的是什

么。例如:

#endif /* #ifndef FILENAME_H */

我个人没有这个习惯,因为这其实是很明显的。当然这只是各人的 风格不

同,无伤大雅。

你只需要在那些有编译错误的 header 档中加入这个技巧,但在所 有的 h

eader 档中都加入也没什么损失,到底这是个好习惯。

1.5 重新编译一个多文件项目

清楚的区别编译和连接是很重要的。编译器使用源码文件来产生某种 形式

的目标文件(object files)。在这个过程中,外部的符号参考并 没有被解

释或替换。然后我们使用连接器来连接这些目标文件和一些 标准的程序包

再加你指定的程序包,最后连接生成一个可执行程序。 在这个阶段,一个

目标文件中对别的文件中的符号的参考被解释,并 报告不能被解释的参考

,一般是以错误信息的形式报告出来。

基本的步骤就应该是,把你的源码文件一个一个的编译成目标文件的格 式

,最后把所有的目标文件加上需要的程序包连接成一个可执行文件。 具体

怎么做是由你的编译器决定的。这里我只给出 gcc (GNU C 编译 器)的有

关命令,这些有可能对你的非 gcc 编译器也适用。

gcc 是一个多目标的工具。它在需要的时候呼叫其它的元件(预处理 程序

,编译器,组合程序,连接器)。具体的哪些元件被呼叫取决于 输入文件

的类型和你传递给它的开关。

一般来说,如果你只给它C源码文件,它将预处理,编译,组合所有 的文

件,然后把所得的目标文件连接成一个可执行文件(一般生成的 文件被命

名为 a.out )。你当然可以这么做,但这会破坏很多我们 把一个项目分解

成多个文件所得到的好处。

如果你给它一个 -c 开关,gcc 只把给它的文件编译成目标文件, 用源码

文件的文件名命名但把其后缀由“.c”或“.cc”变成“.o”。 如果你给它

的是一列目标文件, gcc 会把它们连接成可执行文件, 缺省文件名是 a.

out 。你可以改变缺省名,用开关 -o 后跟你指定 的文件名。

因此,当你改变了一个源码文件后,你需要重新编译它: ‘gcc -c filena

me.c’ 然后重新连接你的项目: ‘gcc -o exec_filename *.o’。 如果你改

变了一个 header 档,你需要重新编译所有 #include 过 这个档的源码文

件,你可以用 ‘gcc -c file1.c file2.c file3.c’ 然后象上边一样连接。

当然这么做是很繁琐的,幸亏我们有些工具使这个步骤变得简单。 本文的

第二部分就是介绍其中的一件工具:GNU Make 工具。

(好家伙,现在才开始见真章。您学到点儿东西没?)

2) GNU Make 工具

~~~~~~~~~~~~~~~~

2.1 基本 makefile 结构

GNU Make 的主要工作是读进一个文本文件, makefile 。这个文 件里主要

是有关哪些文件(‘target’目的文件)是从哪些别的 文件(‘dependen

cies’依靠文件)中产生的,用什么命令来进行 这个产生过程。有了这些

信息, make 会检查磁碟上的文件,如果 目的文件的时间戳(该文件生成

或被改动时的时间)比至少它的一 个依靠文件旧的话, make 就执行相应

的命令,以便更新目的文件。 (目的文件不一定是最后的可执行档,它可

以是任何一个文件。)

makefile 一般被叫做“makefile”或“Makefile”。当然你可以 在 make

 的命令行指定别的文件名。如果你不特别指定,它会寻 找“makefile”或

“Makefile”,因此使用这两个名字是最简单 的。

一个 makefile 主要含有一系列的规则,如下:

: …

(tab)<command>

(tab)<command>

.

.

.

例如,考虑以下的 makefile :

=== makefile 开始 ===

myprog : foo.o bar.o

  gcc foo.o bar.o -o myprog

foo.o : foo.c foo.h bar.h

  gcc -c foo.c -o foo.o

bar.o : bar.c bar.h

  gcc -c bar.c -o bar.o

=== makefile 结束 ===

这是一个非常基本的 makefile ―― make 从最上面开始,把上 面第一个

目的,‘myprog’,做为它的主要目标(一个它需要保 证其总是最新的最

终目标)。给出的规则说明只要文件‘myprog’ 比文件‘foo.o’或‘bar

.o’中的任何一个旧,下一行的命令将 会被执行。

但是,在检查文件 foo.o 和 bar.o 的时间戳之前,它会往下查 找那些把

 foo.o 或 bar.o 做为目标文件的规则。它找到的关于 foo.o 的规则,该

文件的依靠文件是 foo.c, foo.h 和 bar.h 。 它从下面再找不到生成这些

依靠文件的规则,它就开始检查磁碟 上这些依靠文件的时间戳。如果这些

文件中任何一个的时间戳比 foo.o 的新,命令 ‘gcc -o foo.o foo.c’ 将

会执行,从而更新 文件 foo.o 。

接下来对文件 bar.o 做类似的检查,依靠文件在这里是文件 bar.c 和 ba

r.h 。

现在, make 回到‘myprog’的规则。如果刚才两个规则中的任 何一个被

执行,myprog 就需要重建(因为其中一个 .o 档就会比 ‘myprog’新),

因此连接命令将被执行。

希望到此,你可以看出使用 make 工具来建立程序的好处――前 一章中所

有繁琐的检查步骤都由 make 替你做了:检查时间戳。 你的源码文件里一

个简单改变都会造成那个文件被重新编译(因 为 .o 文件依靠 .c 文件)

,进而可执行文件被重新连接(因为 .o 文件被改变了)。其实真正的得益

是在当你改变一个 header 档的时候――你不再需要记住那个源码文件依靠

它,因为所有的 资料都在 makefile 里。 make 会很轻松的替你重新编译

所有那 些因依靠这个 header 文件而改变了的源码文件,如有需要,再 进

行重新连接。

当然,你要确定你在 makefile 中所写的规则是正确无误的,只 列出那些

在源码文件中被 #include 的 header 档……

2.2 编写 make 规则 (Rules)

最明显的(也是最简单的)编写规则的方法是一个一个的查 看源码文件,

把它们的目标文件做为目的,而C源码文件和被它 #include 的 header 档

做为依靠文件。但是你也要把其它被这些 header 档 #include 的 header

 档也列为依靠文件,还有那些被 包括的文件所包括的文件……然后你会发

现要对越来越多的文件 进行管理,然后你的头发开始脱落,你的脾气开始

变坏,你的脸 色变成菜色,你走在路上开始跟电线杆子碰撞,终于你捣毁

你的 电脑显示器,停止编程。到低有没有些容易点儿的方法呢?

当然有!向编译器要!在编译每一个源码文件的时候,它实在应 该知道应

该包括什么样的 header 档。使用 gcc 的时候,用 -M 开关,它会为每一

个你给它的C文件输出一个规则,把目标文件 做为目的,而这个C文件和

所有应该被 #include 的 header 文 件将做为依靠文件。注意这个规则会

加入所有 header 文件,包 括被角括号(`<’, `>’)和双引号(`”‘)所包围的

文件。其实我们可以 相当肯定系统 header 档(比如 stdio.h, stdlib.h

 等等)不会 被我们更改,如果你用 -MM 来代替 -M 传递给 gcc,那些用

角括 号包围的 header 档将不会被包括。(这会节省一些编译时间)

由 gcc 输出的规则不会含有命令部分;你可以自己写入你的命令 或者什么

也不写,而让 make 使用它的隐含的规则(参考下面的 2.4 节)。

2.3 Makefile 变量

上面提到 makefiles 里主要包含一些规则。它们包含的其它的东 西是变量

定义。

makefile 里的变量就像一个环境变量(environment variable)。 事实上,

环境变量在 make 过程中被解释成 make 的变量。这些 变量是大小写敏感

的,一般使用大写字母。它们可以从几乎任何 地方被引用,也可以被用来

做很多事情,比如:

i) 贮存一个文件名列表。在上面的例子里,生成可执行文件的 规则包含一

些目标文件名做为依靠。在这个规则的命令行 里同样的那些文件被输送给

 gcc 做为命令参数。如果在这 里使用一个变数来贮存所有的目标文件名,

加入新的目标 文件会变的简单而且较不易出错。

ii) 贮存可执行文件名。如果你的项目被用在一个非 gcc 的系 统里,或者

如果你想使用一个不同的编译器,你必须将所 有使用编译器的地方改成用

新的编译器名。但是如果使用一 个变量来代替编译器名,那么你只需要改

变一个地方,其 它所有地方的命令名就都改变了。

iii) 贮存编译器旗标。假设你想给你所有的编译命令传递一组 相同的选项

(例如 -Wall -O -g);如果你把这组选项存 入一个变量,那么你可以把

这个变量放在所有呼叫编译器 的地方。而当你要改变选项的时候,你只需

在一个地方改 变这个变量的内容。

要设定一个变量,你只要在一行的开始写下这个变量的名字,后 面跟一个

 = 号,后面跟你要设定的这个变量的值。以后你要引用 这个变量,写一个

 $ 符号,后面是围在括号里的变量名。比如在 下面,我们把前面的 make

file 利用变量重写一遍:

=== makefile 开始 ===

OBJS = foo.o bar.o

CC = gcc

CFLAGS = -Wall -O -g

myprog : $(OBJS)

  $(CC) $(OBJS) -o myprog

foo.o : foo.c foo.h bar.h

  $(CC) $(CFLAGS) -c foo.c -o foo.o

bar.o : bar.c bar.h

  $(CC) $(CFLAGS) -c bar.c -o bar.o

=== makefile 结束 ===

还有一些设定好的内部变量,它们根据每一个规则内容定义。三个 比较有

用的变量是 $@, $< 和 $^ (这些变量不需要括号括住)。 $@ 扩展成当前

规则的目的文件名, $< 扩展成依靠列表中的第 一个依靠文件,而 $^ 扩

展成整个依靠的列表(除掉了里面所有重 复的文件名)。利用这些变量,

我们可以把上面的 makefile 写成:

=== makefile 开始 ===

OBJS = foo.o bar.o

CC = gcc

CFLAGS = -Wall -O -g

myprog : $(OBJS)

  $(CC) $^ -o $@

foo.o : foo.c foo.h bar.h

  $(CC) $(CFLAGS) -c $< -o $@

bar.o : bar.c bar.h

  $(CC) $(CFLAGS) -c $< -o $@

=== makefile 结束 ===

你可以用变量做许多其它的事情,特别是当你把它们和函数混合 使用的时

候。如果需要更进一步的了解,请参考 GNU Make 手册。 (’man make’, ‘

man makefile’)

2.4 隐含规则 (Implicit Rules)

请注意,在上面的例子里,几个产生 .o 文件的命令都是一样的。 都是从

 .c 文件和相关文件里产生 .o 文件,这是一个标准的步 骤。其实 make

已经知道怎么做――它有一些叫做隐含规则的内 置的规则,这些规则告诉

它当你没有给出某些命令的时候,应该 怎么办。

如果你把生成 foo.o 和 bar.o 的命令从它们的规则中删除, make 将会查

找它的隐含规则,然后会找到一个适当的命令。它的命令会 使用一些变量

,因此你可以按照你的想法来设定它:它使用变量 CC 做为编译器(象我们

在前面的例子),并且传递变量 CFLAGS (给 C 编译器,C++ 编译器用 C

XXFLAGS ),CPPFLAGS ( C 预 处理器旗标), TARGET_ARCH (现在不用

考虑这个),然后它加 入旗标 ‘-c’ ,后面跟变量 $< (第一个依靠名)

,然后是旗 标 ‘-o’ 跟变量 $@ (目的文件名)。一个C编译的具体命令

将 会是:

$(CC) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c $< -o $@

当然你可以按照你自己的需要来定义这些变量。这就是为什么用 gcc 的 -

M 或 -MM 开关输出的码可以直接用在一个 makefile 里。

2.5 假象目的 (Phony Targets)

假设你的一个项目最后需要产生两个可执行文件。你的主要目标 是产生两

个可执行文件,但这两个文件是相互独立的――如果一 个文件需要重建,

并不影响另一个。你可以使用“假象目的”来 达到这种效果。一个假象目

的跟一个正常的目的几乎是一样的, 只是这个目的文件是不存在的。因此

, make 总是会假设它需要 被生成,当把它的依赖文件更新后,就会执行

它的规则里的命令 行。

如果在我们的 makefile 开始处输入:

all : exec1 exec2

其中 exec1 和 exec2 是我们做为目的的两个可执行文件。 make 把这个

‘all’ 做为它的主要目的,每次执行时都会尝试把 ‘all’ 更新。但既然这

行规则里没有哪个命令来作用在一个叫 ‘all’ 的 实际文件(事实上 all

并不会在磁碟上实际产生),所以这个规 则并不真的改变 ‘all’ 的状态。

可既然这个文件并不存在,所以 make 会尝试更新 all 规则,因此就检查

它的依靠 exec1, exec2 是否需要更新,如果需要,就把它们更新,从而达

到我们的目的。

假象目的也可以用来描述一组非预设的动作。例如,你想把所有由 make 产

生的文件删除,你可以在 makefile 里设立这样一个规则:

veryclean :

  rm *.o

  rm myprog

前提是没有其它的规则依靠这个 ‘veryclean’ 目的,它将永远 不会被执行

。但是,如果你明确的使用命令 ‘make veryclean’ , make 会把这个目的

做为它的主要目标,执行那些 rm 命令。

如果你的磁碟上存在一个叫 veryclean 文件,会发生什么事?这 时因为在

这个规则里没有任何依靠文件,所以这个目的文件一定是 最新的了(所有

的依靠文件都已经是最新的了),所以既使用户明 确命令 make 重新产生

它,也不会有任何事情发生。解决方法是标 明所有的假象目的(用 .PHON

Y),这就告诉 make 不用检查它们 是否存在于磁碟上,也不用查找任何隐

含规则,直接假设指定的目 的需要被更新。在 makefile 里加入下面这行

包含上面规则的规则:

.PHONY : veryclean

就可以了。注意,这是一个特殊的 make 规则,make 知道 .PHONY 是一个

特殊目的,当然你可以在它的依靠里加入你想用的任何假象 目的,而 mak

e 知道它们都是假象目的。

2.6 函数 (Functions)

makefile 里的函数跟它的变量很相似――使用的时候,你用一个 $ 符号跟

开括号,函数名,空格后跟一列由逗号分隔的参数,最后 用关括号结束。

例如,在 GNU Make 里有一个叫 ‘wildcard’ 的函 数,它有一个参数,功

能是展开成一列所有符合由其参数描述的文 件名,文件间以空格间隔。你

可以像下面所示使用这个命令:

SOURCES = $(wildcard *.c)

这行会产生一个所有以 ‘.c’ 结尾的文件的列表,然后存入变量 SOURCES

里。当然你不需要一定要把结果存入一个变量。

另一个有用的函数是 patsubst ( patten substitude, 匹配替 换的缩写

)函数。它需要3个参数――第一个是一个需要匹配的 式样,第二个表示

用什么来替换它,第三个是一个需要被处理的 由空格分隔的字列。例如,

处理那个经过上面定义后的变量,

OBJS = $(patsubst %.c,%.o,$(SOURCES))

这行将处理所有在 SOURCES 字列中的字(一列文件名),如果它的 结尾是

 ’.c’ ,就用 ‘.o’ 把 ‘.c’ 取代。注意这里的 % 符号将匹 配一个或多个

字符,而它每次所匹配的字串叫做一个‘柄’(stem) 。 在第二个参数里,

 % 被解读成用第一参数所匹配的那个柄。

2.7 一个比较有效的 makefile

利用我们现在所学的,我们可以建立一个相当有效的 makefile 。 这个 m

akefile 可以完成大部分我们需要的依靠检查,不用做太大 的改变就可直

接用在大多数的项目里。

首先我们需要一个基本的 makefile 来建我们的程序。我们可以让 它搜索

当前目录,找到源码文件,并且假设它们都是属于我们的项 目的,放进一

个叫 SOURCES 的变量。这里如果也包含所有的 *.cc 文件,也许会更保险

,因为源码文件可能是 C++ 码的。

SOURCES = $(wildcard *.c *.cc)

利用 patsubst ,我们可以由源码文件名产生目标文件名,我们需 要编译

出这些目标文件。如果我们的源码文件既有 .c 文件,也有 .cc 文件,我

们需要使用相嵌的 patsubst 函数呼叫:

OBJS = $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCES)))

最里面一层 patsubst 的呼叫会对 .cc 文件进行后缀替代,产生的结 果被

外层的 patsubst 呼叫处理,进行对 .c 文件后缀的替代。

现在我们可以设立一个规则来建可执行文件:

myprog : $(OBJS)

  gcc -o myprog $(OBJS)

进一步的规则不一定需要, gcc 已经知道怎么去生成目标文件 (object f

iles) 。下面我们可以设定产生依靠信息的规则:

depends : $(SOURCES)

  gcc -M $(SOURCES) > depends

在这里如果一个叫 ‘depends’ 的文件不存在,或任何一个源码文件 比一个

已存在的 depends 文件新,那么一个 depends 文件会被生 成。depends

文件将会含有由 gcc 产生的关于源码文件的规则(注 意 -M 开关)。现在

我们要让 make 把这些规则当做 makefile 档 的一部分。这里使用的技巧

很像 C 语言中的 #include 系统――我 们要求 make 把这个文件 includ

e 到 makefile 里,如下:

include depends

GNU Make 看到这个,检查 ‘depends’ 目的是否更新了,如果没有, 它用

我们给它的命令重新产生 depends 档。然后它会把这组(新) 规则包含进

来,继续处理最终目标 ‘myprog’ 。当看到有关 myprog 的规则,它会检查

所有的目标文件是否更新――利用 depends 文件 里的规则,当然这些规则

现在已经是更新过的了。

这个系统其实效率很低,因为每当一个源码文件被改动,所有的源码 文件

都要被预处理以产生一个新的 ‘depends’ 文件。而且它也不是 100% 的安

全,这是因为当一个 header 档被改动,依靠信息并不会 被更新。但就基

本工作来说,它也算相当有用的了。

2.8 一个更好的 makefile

这是一个我为我大多数项目设计的 makefile 。它应该可以不需要修 改的

用在大部分项目里。我主要把它用在 djgpp 上,那是一个 DOS 版的 gcc

编译器。因此你可以看到执行的命令名、 ‘alleg’ 程序包、 和 RM -F 变

量都反映了这一点。

=== makefile 开始 ===

######################################

#

# Generic makefile

#

# by George Foot

# email: george.foot@merton.ox.ac.uk

#

# Copyright (c) 1997 George Foot

# All rights reserved.

# 保留所有版权

#

# No warranty, no liability;

# you use this at your own risk.

# 没保险,不负责

# 你要用这个,你自己担风险

#

# You are free to modify and

# distribute this without giving

# credit to the original author.

# 你可以随便更改和散发这个文件

# 而不需要给原作者什么荣誉。

# (你好意思?)

#

######################################

### Customising

# 用户设定

#

# Adjust the following if necessary; EXECUTABLE is the target

# executable’s filename, and LIBS is a list of libraries to link

in

# (e.g. alleg, stdcx, iostr, etc). You can override these on make

’s

# command line of course, if you prefer to do it that way.

#

# 如果需要,调整下面的东西。 EXECUTABLE 是目标的可执行文件名, LI

BS

# 是一个需要连接的程序包列表(例如 alleg, stdcx, iostr 等等)。当

然你

# 可以在 make 的命令行覆盖它们,你愿意就没问题。

#

EXECUTABLE := mushroom.exe

LIBS := alleg

# Now alter any implicit rules’ variables if you like, e.g.:

#

# 现在来改变任何你想改动的隐含规则中的变量,例如

CFLAGS := -g -Wall -O3 -m486

CXXFLAGS := $(CFLAGS)

# The next bit checks to see whether rm is in your djgpp bin

# directory; if not it uses del instead, but this can cause (harm

less)

# `File not found’ error messages. If you are not using DOS at al

l,

# set the variable to something which will unquestioningly remove

# files.

#

# 下面先检查你的 djgpp 命令目录下有没有 rm 命令,如果没有,我们使

# del 命令来代替,但有可能给我们 ‘File not found’ 这个错误信息,这

# 什么大碍。如果你不是用 DOS ,把它设定成一个删文件而不废话的命令

# (其实这一步在 UNIX 类的系统上是多余的,只是方便 DOS 用户。 UNI

X

# 用户可以删除这5行命令。)

ifneq ($(wildcard $(DJDIR)/bin/rm.exe),)

RM-F := rm -f

else

RM-F := del

endif

# You shouldn’t need to change anything below this point.

#

# 从这里开始,你应该不需要改动任何东西。(我是不太相信,太NB了!

SOURCE := $(wildcard *.c) $(wildcard *.cc)

OBJS := $(patsubst %.c,%.o,$(patsubst %.cc,%.o,$(SOURCE)))

DEPS := $(patsubst %.o,%.d,$(OBJS))

MISSING_DEPS := $(filter-out $(wildcard $(DEPS)),$(DEPS))

MISSING_DEPS_SOURCES := $(wildcard $(patsubst %.d,%.c,$(MISSING_D

EPS)) \

$(patsubst %.d,%.cc,$(MISSING_DEPS)))

CPPFLAGS += -MD

.PHONY : everything deps objs clean veryclean rebuild

everything : $(EXECUTABLE)

deps : $(DEPS)

objs : $(OBJS)

clean :

  @$(RM-F) *.o

  @$(RM-F) *.d

veryclean: clean

  @$(RM-F) $(EXECUTABLE)

rebuild: veryclean everything

ifneq ($(MISSING_DEPS),)

$(MISSING_DEPS) :

  @$(RM-F) $(patsubst %.d,%.o,$@)

endif

-include $(DEPS)

$(EXECUTABLE) : $(OBJS)

  gcc -o $(EXECUTABLE) $(OBJS) $(addprefix -l,$(LIBS))

=== makefile 结束 ===

有几个地方值得解释一下的。首先,我在定义大部分变量的时候使 用的是

 := 而不是 = 符号。它的作用是立即把定义中参考到的函 数和变量都展开

了。如果使用 = 的话,函数和变量参考会留在那 儿,就是说改变一个变量

的值会导致其它变量的值也被改变。例 如:

A = foo

B = $(A)

# 现在 B 是 $(A) ,而 $(A) 是 ‘foo’ 。

A = bar

# 现在 B 仍然是 $(A) ,但它的值已随着变成 ‘bar’ 了。

B := $(A)

# 现在 B 的值是 ‘bar’ 。

A = foo

# B 的值仍然是 ‘bar’ 。

make 会忽略在 # 符号后面直到那一行结束的所有文字。

ifneg…else…endif 系统是 makefile 里让某一部分码有条件的 失效/

有效的工具。 ifeq 使用两个参数,如果它们相同,它把直 到 else (或

者 endif ,如果没有 else 的话)的一段码加进 makefile 里;如果不同

,把 else 到 endif 间的一段码加入 makefile (如果有 else )。 ifn

eq 的用法刚好相反。

‘filter-out’ 函数使用两个用空格分开的列表,它把第二列表中所 有的存

在于第一列表中的项目删除。我用它来处理 DEPS 列表,把所 有已经存在

的项目都删除,而只保留缺少的那些。

我前面说过, CPPFLAGS 存有用于隐含规则中传给预处理器的一些 旗标。

而 -MD 开关类似 -M 开关,但是从源码文件 .c 或 .cc 中 形成的文件名

是使用后缀 .d 的(这就解释了我形成 DEPS 变量的 步骤)。DEPS 里提到

的文件后来用 ‘-include’ 加进了 makefile 里,它隐藏了所有因文件不存

在而产生的错误信息。

如果任何依靠文件不存在, makefile 会把相应的 .o 文件从磁碟 上删除

,从而使得 make 重建它。因为 CPPFLAGS 指定了 -MD , 它的 .d 文件也

被重新产生。

最后, ‘addprefix’ 函数把第二个参数列表的每一项前缀上第一 个参数值

这个 makefile 的那些目的是(这些目的可以传给 make 的命令行 来直接

选用):

everything:(预设) 更新主要的可执行程序,并且为每一个 源码文件生

成或更新一个 ‘.d’ 文件和一个 ‘.o’ 文件。

deps: 只是为每一个源码程序产生或更新一个 ‘.d’ 文件。

objs: 为每一个源码程序生成或更新 ‘.d’ 文件和目标文件。

clean: 删除所有中介/依靠文件( *.d 和 *.o )。

veryclean: 做 `clean’ 和删除可执行文件。

rebuild: 先做 `veryclean’ 然后 `everything’ ;既完全重建。

除了预设的 everything 以外,这里头只有 clean , veryclean , 和 r

ebuild 对用户是有意义的。

我还没有发现当给出一个源码文件的目录,这个 makefile 会失败的 情况

,除非依靠文件被弄乱。如果这种弄乱的情况发生了,只要输入 `make cl

ean’ ,所有的目标文件和依靠文件会被删除,问题就应该 被解决了。当然

,最好不要把它们弄乱。如果你发现在某种情况下这 个 makefile 文件不

能完成它的工作,请告诉我,我会把它整好的。

3 总结

~~~~~~~~~~~~~~~

我希望这篇文章足够详细的解释了多文件项目是怎么运作的,也说明了 怎

样安全而合理的使用它。到此,你应该可以轻松的利用 GNU Make 工 具来

管理小型的项目,如果你完全理解了后面几个部分的话,这些对于 你来说

应该没什么困难。

GNU Make 是一件强大的工具,虽然它主要是用来建立程序,它还有很多 别

的用处。如果想要知道更多有关这个工具的知识,它的句法,函数, 和许

多别的特点,你应该参看它的参考文件 (info pages, 别的 GNU 工具也一

样,看它们的 info pages. )。

—————————————————————–

—————

C Scene 官方网站: http://cscene.differnet.org

C Scene 官方电邮: cscene@mindless.com

—————————————————————–

—————

This page is Copyright ? 1997 By C Scene. All Rights Reserved

—————————————————————–

—————

Posted in 他山之石, 学海无涯 | No Comments

82C50A

01月 14th, 2005 by solarsea

     串口也是板子I/O的一部分,当前实现的功能仅仅是串口是通的,可以通过串口读取一些数据。李老师希望能够通过串口实现一些控制功能,因此这也算是毕设的一部分了,于是这两天集中看了一些和串口有关的东西。
     RS-232是早期为公用电话网络数据通信而制定的标准(应该就是用于modem了吧),其逻辑电平与TTL/CMOS完全不同。逻辑0规定为+5~+15V之间,逻辑1规定为-5~-15V之间。因此,必须进行电平转换。具体到板子上,就是采用了Maxim的Max232来实现串口和82C50A之间的电平转换。看了82C50A的datasheet,对整个芯片的工作模式以及内部寄存器设置有了了解,再看师兄留下的驱动程序就完全能够明白了,数据处理都是通过中断服务程序进行的。以接收为例,在接收缓存寄存器满的时候会触发相应的中断,于是中断服务程序被调用,在ISR里检测中断类型,然后作出相应的处理,或者创建一个新任务处理命令。一天半下来,有一种豁然开朗的感觉,虽然不是什么深奥难懂的东西,但明白了以后还是觉得很有收获。至于这一部分的调试,还要等到新的jtag板买回来才可以,明天全老师那边换新板子,李老师要求过去看一下,和旧板是否兼容,可以的话,我们也买一块。

Posted in 校园拾贝, 毕业进行时 | No Comments

Macro

01月 12th, 2005 by solarsea

     这几天都在看TM1300文档中和VIVO有关的部分,主要是想大致搞清楚在我们的系统里使用到的,并且被师兄封装好的那些接口函数的作用。看了databook和book7中的相关部分之后,对整个TM1300的VI和VO部分有了一些初浅的认识,再看师兄留下的视频接口函数,已经大致能搞清楚那些函数的实现了。在看代码的过程中,不断要到TriMedia的include目录下和VIVO相关的头文件中查看相关的声明,宏定义等信息,于是也仔细看了那些头文件,收获真不少啊,主要是宏的使用,举例如下。
     
/******************** Y_THRESHOLD (Control:20-31) **********************/
#define  VI_Y_THRESHOLD_SHIFT     20U
#define  VI_Y_THRESHOLD_MASK      0xfff
#define  VI_Y_THRESHOLD           (VI_Y_THRESHOLD_MASK << \ VI_Y_THRESHOLD_SHIFT)

#define  viExtractY_THRESHOLD(x)  (((x) >> VI_Y_THRESHOLD_SHIFT) & VI_Y_THRESHOLD_MASK)
#define  viInsertY_THRESHOLD(y,x) ((y) = ((y)&~VI_Y_THRESHOLD)|((x)<<VI_Y_THRESHOLD_SHIFT))
#define  viInsertY_THRESHOLD__CHECK(y,x) \
    {tmAssert(((x)&~VI_Y_THRESHOLD_MASK)==0,VI_ERR_Y_THRESHOLD_SIZE); \
    viInsertY_THRESHOLD(y,x); \
    }

#define  viSetY_THRESHOLD__CHECKM(b,x)     viInsertY_THRESHOLD__CHECK(MMIO(b+VI_CTL_OFFSET),x)
#define  viSetY_THRESHOLDM(b,x)            viInsertY_THRESHOLD(MMIO(b+VI_CTL_OFFSET),x)
#define  viGetY_THRESHOLDM(b)              viExtractY_THRESHOLD(MMIO(b+VI_CTL_OFFSET))

#define  viSetY_THRESHOLD__CHECK(x)        viSetY_THRESHOLD__CHECKM(VI_STATUS,x)
#define  viSetY_THRESHOLD(x)               viSetY_THRESHOLDM(VI_STATUS,x)
#define  viGetY_THRESHOLD()                viGetY_THRESHOLDM(VI_STATUS)
    
     上面是tmVImmio.h中有关Y_THRESHOLD的宏。Y_THRESHOLD一共12bit,位于控制字VI_CTL的第20-31位。用户使用的时候,只要通过宏viSetY_THRESHOLD__CHECKM(b,x),就可以把x填入控制字b的相应位置。
     具体实现的时候,宏viSetY_THRESHOLD__CHECKM(b,x)被展开为viInsertY_THRESHOLD__CHECK(MMIO(b+VI_CTL_OFFSET),x),这依然是一个宏,再接着被展开。这里用了assert检查输入的有效性,然后再度通过宏展开成了viInsertY_THRESHOLD(y,x);这个宏最后通过一开始定义的宏SHIFT和MASK对输入参数进行移位和与或操作,最终把用户希望设定 的值写入控制字的相应位。
     虽然稍有常识的程序员都应该知道,位操作是通过移位和与或来实现的,但如此使用宏,带来这般便利,至少让我深刻认识到水平的巨大差异。以前知道MFC中也大量使用到了宏,比如要让一个类可以动态创建,需要DECLARE_DYNCREATE和IMPLEMENT_DYNCREATE宏,消息映射机制,也要相应的BEGIN_MESSAGE_MAP和END_MESSAGE_MAP宏,看了jjHou的Deserting MFC之后,也深入了一步,但这一次深刻体会到了编程语言的强大,计算技术的强大,人类智慧的强大,以及自己的渺小,当然也坚定了继续努力的决心。
     吃晚饭前,把电子版的c programming language找了出来,仔细看了一下附录的standard library,因为最近遇到了不少标准库里的函数,都不知道该怎么用,查MSDN虽然也很方便,但觉得怎么也应该好好看一看的,下回用的时候才能心里有数。本科的时候,专业是通信工程,大二的时候,用谭浩强那本c程序设计自学的c语言,印象里头书里好像没有专门介绍标准库,因为标准库不是c语言的内容。后来学了C++,但那个老师实在搞笑,老头估计搞了太长时间的过程编程,自己都没明白OO是什么,有一种说法把C++说成是带类的C,但我们当时学的,只能叫不带类的C++,除了把printf和scanf换成了cout和cin,别的全按c讲的,呵呵,没讲class,能叫C++吗?不过本科的时候实在对编程要求不高,毕设做了个理论探讨就算过关了,重点大学的教育水平也不过如此啊,sigh。现在想来,常常惋惜当初没有好好学计算机,有时间都玩儿去了。其实编程还是应该理论和实践结合的,这样进步才能快一些。光有理论,都是空谈;光有实践,到了一定层次就很难提高了,而说到理论,除了编程语言本身,编译原理,操作系统,软件工程…学无止境啊。

Posted in 校园拾贝, 毕业进行时 | No Comments

« Previous Entries

登录 | 访问数284866 | 水木BLOG | 水木社区 | 关于我们 | Blog论坛 | 法律声明 | 隐私权保护 | 京ICP证050249号
水木社区Blog系统是基于KBS系统WordPress MU架构的