﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>IT博客-&lt;font size='6'&gt;陋石&lt;/font&gt;</title><link>http://www.cnitblog.com/lainding/</link><description>&lt;!--
&lt;object id="MediaPlayer1" classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715" standby="Loading Microsoft Windows Media Player components..." type="application/x-oleobject" align="bottom" border="0" height="0" width="0"&gt;
				&lt;param name="FileName" value="http://www.nowhy.cn/music/luanhong.wma"&gt;
				&lt;param name="ShowControls" value="0"&gt;
				&lt;param name="ShowPositionControls" value="0"&gt;
				&lt;param name="ShowAudioControls" value="0"&gt;
				&lt;param name="ShowTracker" value="0"&gt;
				&lt;param name="ShowDisplay" value="0"&gt;
				&lt;param name="ShowStatusBar" value="0"&gt;
				&lt;param name="AutoSize" value="0"&gt;
				&lt;param name="ShowGotoBar" value="0"&gt;
				&lt;param name="ShowCaptioning" value="0"&gt;
				&lt;param name="AutoStart" value="1"&gt;
				&lt;param name="PlayCount" value="0"&gt;
				&lt;param name="AnimationAtStart" value="0"&gt;
				&lt;param name="TransparentAtStart" value="0"&gt;
				&lt;param name="AllowScan" value="0"&gt;
				&lt;param name="EnableContextMenu" value="0"&gt;
				&lt;param name="ClickToPlay" value="0"&gt;
				&lt;param name="InvokeURLs" value="0"&gt;
				&lt;param name="DefaultFrame" value="datawindow"&gt;
				&lt;embed src="http://www.nowhy.cn/music/luanhong.wma" type="application/x-mplayer2" pluginspage="http://www.microsoft.com/isapi/redir.dll?prd=windows&amp;amp;sbp=mediaplayer&amp;amp;ar=media&amp;amp;sba=plugin&amp;amp;" name="MediaPlayer" showcontrols="0" showpositioncontrols="0" showaudiocontrols="0" showtracker="1" showdisplay="0" showstatusbar="0" autosize="0" showgotobar="0" showcaptioning="0" autostart="0" autorewind="0" animationatstart="0" transparentatstart="0" allowscan="0" enablecontextmenu="1" clicktoplay="0" invokeurls="0" defaultframe="datawindow" align="bottom" border="0" height="0" width="0"&gt;
				
		&lt;/object&gt;
--&gt;</description><language>zh-cn</language><lastBuildDate>Wed, 29 Apr 2026 05:58:56 GMT</lastBuildDate><pubDate>Wed, 29 Apr 2026 05:58:56 GMT</pubDate><ttl>60</ttl><item><title>Linux开发环境的构成</title><link>http://www.cnitblog.com/lainding/archive/2006/07/13/13612.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Thu, 13 Jul 2006 14:44:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/13/13612.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13612.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/13/13612.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13612.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13612.html</trackback:ping><description><![CDATA[Linux下的开发环境<br /><ul><li>编辑器：VI</li><li>编译器：GNU C/C++编译器gcc(GNU C Compiler)<br /></li><li>调试器：应用广泛的gdb</li><li>函数库：glibc</li><li>系统头文件：glibc_header</li></ul><br />Linux下的IDE<br /><ul><li>Kylix：号称Linux下的dephi</li><li>Kdevelop</li><li>RHIDE：类似于Turbo C++<br /></li></ul><img src ="http://www.cnitblog.com/lainding/aggbug/13612.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-13 22:44 <a href="http://www.cnitblog.com/lainding/archive/2006/07/13/13612.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>想成为嵌入式程序员所必须了解的C问题</title><link>http://www.cnitblog.com/lainding/archive/2006/07/11/13509.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Tue, 11 Jul 2006 12:54:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/11/13509.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13509.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/11/13509.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13509.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13509.html</trackback:ping><description><![CDATA[C语言测试是招聘嵌入式系统程序员过程中必须而且有效的方法。这些年，我既参加也组织<br /><br />了许多这种测试，在这过程中我意识到这些测试能为带面试者和被面试者提供许多有用信<br /><br />息，此外，撇开面试的压力不谈，这种测试也是相当有趣的。<br />从被面试者的角度来讲，你能了解许多关于出题者或监考者的情况。这个测试只是出题者<br /><br />为显示其对ANSI标准细节的知识而不是技术技巧而设计吗？这个愚蠢的问题吗？如要你答<br /><br />出某个字符的ASCII值。这些问题着重考察你的系统调用和内存分配策略方面的能力吗？这<br /><br />标志着出题者也许花时间在微机上而不上在嵌入式系统上。如果上述任何问题的答案是“<br /><br />是”的话，那么我知道我得认真考虑我是否应该去做这份工作。<br />从面试者的角度来讲，一个测试也许能从多方面揭示应试者的素质：最基本的，你能了解<br /><br />应试者C语言的水平。不管怎么样，看一下这人如何回答他不会的问题也是满有趣。应试者<br /><br />是以好的直觉做出明智的选择，还是只是瞎蒙呢？当应试者在某个问题上卡住时是找借口<br /><br />呢，还是表现出对问题的真正的好奇心，把这看成学习的机会呢？我发现这些信息与他们<br /><br />的测试成绩一样有用。<br />有了这些想法，我决定出一些真正针对嵌入式系统的考题，希望这些令人头痛的考题能给<br /><br />正在找工作的人一点帮住。这些问题都是我这些年实际碰到的。其中有些题很难，但它们<br /><br />应该都能给你一点启迪。<br />这个测试适于不同水平的应试者，大多数初级水平的应试者的成绩会很差，经验丰富的程<br /><br />序员应该有很好的成绩。为了让你能自己决定某些问题的偏好，每个问题没有分配分数，<br /><br />如果选择这些考题为你所用，请自行按你的意思分配分数。<br />预处理器（Preprocessor）<br /><br />1 . 用预处理指令#define 声明一个常数，用以表明1年中有多少秒（忽略闰年问题）<br /><br /><br />#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL<br />我在这想看到几件事情：<br />&amp;#8226;; #define 语法的基本知识（例如：不能以分号结束，括号的使用，等等）<br /><br /><br />&amp;#8226;; 懂得预处理器将为你计算常数表达式的值，因此，直接写出你是如何计算一年中<br /><br />有多少秒而不是计算出实际的值，是更清晰而没有代价的。<br />&amp;#8226;; 意识到这个表达式将使一个16位机的整型数溢出-因此要用到长整型符号L,告诉<br /><br />编译器这个常数是的长整型数。<br />&amp;#8226;; 如果你在你的表达式中用到UL（表示无符号长整型），那么你有了一个好的起点<br /><br />。记住，第一印象很重要。<br />2 . 写一个“标准”宏MIN ，这个宏输入两个参数并返回较小的一个。<br /><br /><br />#define MIN(A,B) （（A） &lt;= (B) ? (A) : (B)) <br /><br />这个测试是为下面的目的而设的：<br />&amp;#8226;; 标识#define在宏中应用的基本知识。这是很重要的，因为直到嵌入(inline)操<br /><br />作符变为标准C的一部分，宏是方便产生嵌入代码的唯一方法，对于嵌入式系统来说，为了<br /><br />能达到要求的性能，嵌入代码经常是必须的方法。<br />&amp;#8226;; 三重条件操作符的知识。这个操作符存在C语言中的原因是它使得编译器能产生<br /><br />比if-then-else更优化的代码，了解这个用法是很重要的。<br />&amp;#8226;; 懂得在宏中小心地把参数用括号括起来<br />&amp;#8226;; 我也用这个问题开始讨论宏的副作用，例如：当你写下面的代码时会发生什么事<br /><br />？<br /><br />least = MIN(*p++, b);<br /><br /><br />3. 预处理器标识#error的目的是什么？<br />如果你不知道答案，请看参考文献1。这问题对区分一个正常的伙计和一个书呆子是很有用<br /><br />的。只有书呆子才会读C语言课本的附录去找出象这种问题的答案。当然如果你不是在找一<br /><br />个书呆子，那么应试者最好希望自己不要知道答案。<br />死循环（Infinite loops）<br /><br /><br />4. 嵌入式系统中经常要用到无限循环，你怎么样用C编写死循环呢？<br />这个问题用几个解决方案。我首选的方案是：<br /><br />while(1)<br />{<br />?}<br /><br /><br /><br />一些程序员更喜欢如下方案：<br /><br />for(;;)<br />{<br />?}<br /><br /><br /><br />这个实现方式让我为难，因为这个语法没有确切表达到底怎么回事。如果一个应试者给出<br /><br />这个作为方案，我将用这个作为一个机会去探究他们这样做的基本原理。如果他们的基本<br /><br />答案是：“我被教着这样做，但从没有想到过为什么。”这会给我留下一个坏印象。<br />第三个方案是用 goto<br /><br />Loop:<br />...<br />goto Loop;<br /><br /><br />应试者如给出上面的方案，这说明或者他是一个汇编语言程序员（这也许是好事）或者他<br /><br />是一个想进入新领域的BASIC/FORTRAN程序员。<br /><br />数据声明（Data declarations） <br /><br />5. 用变量a给出下面的定义<br />a) 一个整型数（An integer） <br />b)一个指向整型数的指针（ A pointer to an integer） <br />c)一个指向指针的的指针，它指向的指针是指向一个整型数（ A pointer to a pointer <br /><br />to an intege）r <br />d)一个有10个整型数的数组（ An array of 10 integers） <br />e) 一个有10个指针的数组，该指针是指向一个整型数的。（An array of 10 pointers t<br /><br />o integers） <br />f) 一个指向有10个整型数数组的指针（ A pointer to an array of 10 integers） <br />g) 一个指向函数的指针，该函数有一个整型参数并返回一个整型数（A pointer to a fu<br /><br />nction that takes an integer as an argument and returns an integer） <br />h)一个有10个指针的数组，该指针指向一个函数，该函数有一个整型参数并返回一个整型<br /><br />数（ An array of ten pointers to functions that take an integer argument and r<br /><br />eturn an integer ）<br /><br />答案是： <br />a) int a; // An integer <br />b) int *a; // A pointer to an integer <br />c) int **a; // A pointer to a pointer to an integer <br />d) int a[10]; // An array of 10 integers <br />e) int *a[10]; // An array of 10 pointers to integers <br />f) int (*a)[10]; // A pointer to an array of 10 integers <br />g) int (*a)(int); // A pointer to a function a that takes an integer argument <br /><br />and returns an integer <br />h) int (*a[10])(int); // An array of 10 pointers to functions that take an int<br /><br />eger argument and return an integer <br />人们经常声称这里有几个问题是那种要翻一下书才能回答的问题，我同意这种说法。当我<br /><br />写这篇文章时，为了确定语法的正确性，我的确查了一下书。但是当我被面试的时候，我<br /><br />期望被问到这个问题（或者相近的问题）。因为在被面试的这段时间里，我确定我知道这<br /><br />个问题的答案。应试者如果不知道所有的答案（或至少大部分答案），那么也就没有为这<br /><br />次面试做准备，如果该面试者没有为这次面试做准备，那么他又能为什么出准备呢？<br />Static <br />6. 关键字static的作用是什么？<br />这个简单的问题很少有人能回答完全。在C语言中，关键字static有三个明显的作用：<br />&amp;#8226;; 在函数体，一个被声明为静态的变量在这一函数被调用过程中维持其值不变。<br /><br /><br />&amp;#8226;; 在模块内（但在函数体外），一个被声明为静态的变量可以被模块内所用函数访<br /><br />问，但不能被模块外其它函数访问。它是一个本地的全局变量。<br />&amp;#8226;; 在模块内，一个被声明为静态的函数只可被这一模块内的其它函数调用。那就是<br /><br />，这个函数被限制在声明它的模块的本地范围内使用。<br />大多数应试者能正确回答第一部分，一部分能正确回答第二部分，同是很少的人能懂得第<br /><br />三部分。这是一个应试者的严重的缺点，因为他显然不懂得本地化数据和代码范围的好处<br /><br />和重要性。<br /><br /><br />Const <br /><br />7．关键字const有什么含意？<br />我只要一听到被面试者说：“const意味着常数”，我就知道我正在和一个业余者打交道。<br /><br />去年Dan Saks已经在他的文章里完全概括了const的所有用法，因此ESP(译者：Embedded <br /><br />Systems Programming)的每一位读者应该非常熟悉const能做什么和不能做什么.如果你从<br /><br />没有读到那篇文章，只要能说出const意味着“只读”就可以了。尽管这个答案不是完全的<br /><br />答案，但我接受它作为一个正确的答案。（如果你想知道更详细的答案，仔细读一下Saks<br /><br />的文章吧。）<br />如果应试者能正确回答这个问题，我将问他一个附加的问题：<br />下面的声明都是什么意思？<br /><br />const int a;<br />int const a;<br />const int *a;<br />int * const a;<br />int const * a const;<br /><br />/******/<br />前两个的作用是一样，a是一个常整型数。第三个意味着a是一个指向常整型数的指针（也<br /><br />就是，整型数是不可修改的，但指针可以）。第四个意思a是一个指向整型数的常指针（也<br /><br />就是说，指针指向的整型数是可以修改的，但指针是不可修改的）。最后一个意味着a是一<br /><br />个指向常整型数的常指针（也就是说，指针指向的整型数是不可修改的，同时指针也是不<br /><br />可修改的）。如果应试者能正确回答这些问题，那么他就给我留下了一个好印象。顺带提<br /><br />一句，也许你可能会问，即使不用关键字const，也还是能很容易写出功能正确的程序，那<br /><br />么我为什么还要如此看重关键字const呢？我也如下的几下理由：<br />&amp;#8226;; 关键字const的作用是为给读你代码的人传达非常有用的信息，实际上，声明一<br /><br />个参数为常量是为了告诉了用户这个参数的应用目的。如果你曾花很多时间清理其它人留<br /><br />下的垃圾，你就会很快学会感谢这点多余的信息。（当然，懂得用const的程序员很少会留<br /><br />下的垃圾让别人来清理的。）<br />&amp;#8226;; 通过给优化器一些附加的信息，使用关键字const也许能产生更紧凑的代码。<br />&amp;#8226;; 合理地使用关键字const可以使编译器很自然地保护那些不希望被改变的参数，<br /><br />防止其被无意的代码修改。简而言之，这样可以减少bug的出现。<br />Volatile <br /><br />8. 关键字volatile有什么含意?并给出三个不同的例子。<br />一个定义为volatile的变量是说这变量可能会被意想不到地改变，这样，编译器就不会去<br /><br />假设这个变量的值了。精确地说就是，优化器在用到这个变量时必须每次都小心地重新读<br /><br />取这个变量的值，而不是使用保存在寄存器里的备份。下面是volatile变量的几个例子：<br /><br /><br />&amp;#8226;; 并行设备的硬件寄存器（如：状态寄存器）<br />&amp;#8226;; 一个中断服务子程序中会访问到的非自动变量(Non-automatic variables)<br />&amp;#8226;; 多线程应用中被几个任务共享的变量<br /><br />回答不出这个问题的人是不会被雇佣的。我认为这是区分C程序员和嵌入式系统程序员的最<br /><br />基本的问题。搞嵌入式的家伙们经常同硬件、中断、RTOS等等打交道，所有这些都要求用<br /><br />到volatile变量。不懂得volatile的内容将会带来灾难。<br />假设被面试者正确地回答了这是问题（嗯，怀疑是否会是这样），我将稍微深究一下，看<br /><br />一下这家伙是不是直正懂得volatile完全的重要性。<br />&amp;#8226;; 一个参数既可以是const还可以是volatile吗？解释为什么。<br />&amp;#8226;; 一个指针可以是volatile 吗？解释为什么。<br />&amp;#8226;; 下面的函数有什么错误：<br />int square(volatile int *ptr)<br />{<br />return *ptr * *ptr;<br />}<br /><br />下面是答案：<br />&amp;#8226;; 是的。一个例子是只读的状态寄存器。它是volatile因为它可能被意想不到地改<br /><br />变。它是const因为程序不应该试图去修改它。<br />&amp;#8226;; 是的。尽管这并不很常见。一个例子是当一个中服务子程序修该一个指向一个b<br /><br />uffer的指针时。<br />&amp;#8226;; 这段代码有点变态。这段代码的目的是用来返指针*ptr指向值的平方，但是，由<br /><br />于*ptr指向一个volatile型参数，编译器将产生类似下面的代码：<br /><br /><br />int square(volatile int *ptr) <br />{<br />int a,b;<br />a = *ptr;<br />b = *ptr;<br />return a * b;<br />}<br /><br /><br />由于*ptr的值可能被意想不到地该变，因此a和b可能是不同的。结果，这段代码可能返不<br /><br />是你所期望的平方值！正确的代码如下：<br /><br />long square(volatile int *ptr) <br />{<br />int a;<br />a = *ptr;<br />return a * a;<br />}<br /><br />位操作（Bit manipulation） <br /><br />9. 嵌入式系统总是要用户对变量或寄存器进行位操作。给定一个整型变量a，写两段代码<br /><br />，第一个设置a的bit 3，第二个清除a 的bit 3。在以上两个操作中，要保持其它位不变。<br /><br /><br />对这个问题有三种基本的反应<br />&amp;#8226;; 不知道如何下手。该被面者从没做过任何嵌入式系统的工作。<br />&amp;#8226;; 用bit fields。Bit fields是被扔到C语言死角的东西，它保证你的代码在不同<br /><br />编译器之间是不可移植的，同时也保证了的你的代码是不可重用的。我最近不幸看到Infi<br /><br />neon为其较复杂的通信芯片写的驱动程序，它用到了bit fields因此完全对我无用，因为<br /><br />我的编译器用其它的方式来实现bit fields的。从道德讲：永远不要让一个非嵌入式的家<br /><br />伙粘实际硬件的边。<br />&amp;#8226;; 用 #defines 和 bit masks 操作。这是一个有极高可移植性的方法，是应该被<br /><br />用到的方法。最佳的解决方案如下：<br /><br /><br />#define BIT3 (0x1 &lt;&lt; 3)<br />static int a;<br /><br />void set_bit3(void) {<br />a |= BIT3;<br />}<br />void clear_bit3(void) {<br />a &amp;= ~BIT3;<br />}<br /><br />一些人喜欢为设置和清除值而定义一个掩码同时定义一些说明常数，这也是可以接受的。<br /><br />我希望看到几个要点：说明常数、|=和&amp;=~操作。<br />访问固定的内存位置（Accessing fixed memory locations） <br /><br />10. 嵌入式系统经常具有要求程序员去访问某特定的内存位置的特点。在某工程中，要求<br /><br />设置一绝对地址为0x67a9的整型变量的值为0xaa66。编译器是一个纯粹的ANSI编译器。写<br /><br />代码去完成这一任务。<br />这一问题测试你是否知道为了访问一绝对地址把一个整型数强制转换（typecast）为一指<br /><br />针是合法的。这一问题的实现方式随着个人风格不同而不同。典型的类似代码如下：<br /><br />int *ptr;<br />ptr = (int *)0x67a9;<br />*ptr = 0xaa55;<br /><br />A more obscure approach is: <br />一个较晦涩的方法是：<br /><br />*(int * const)(0x67a9) = 0xaa55;<br /><br />即使你的品味更接近第二种方案，但我建议你在面试时使用第一种方案。<br /><br />中断（Interrupts） <br /><br />11. 中断是嵌入式系统中重要的组成部分，这导致了很多编译开发商提供一种扩展—让标<br /><br />准C支持中断。具代表事实是，产生了一个新的关键字__interrupt。下面的代码就使用了<br /><br />__interrupt关键字去定义了一个中断服务子程序(ISR)，请评论一下这段代码的。<br /><br />__interrupt double compute_area (double radius) <br />{<br />double area = PI * radius * radius;<br />printf("\nArea = %f", area);<br />return area;<br />}<br /><br />这个函数有太多的错误了，以至让人不知从何说起了：<br />&amp;#8226;; ISR 不能返回一个值。如果你不懂这个，那么你不会被雇用的。<br />&amp;#8226;; ISR 不能传递参数。如果你没有看到这一点，你被雇用的机会等同第一项。<br />&amp;#8226;; 在许多的处理器/编译器中，浮点一般都是不可重入的。有些处理器/编译器需要<br /><br />让额处的寄存器入栈，有些处理器/编译器就是不允许在ISR中做浮点运算。此外，ISR应该<br /><br />是短而有效率的，在ISR中做浮点运算是不明智的。<br />&amp;#8226;; 与第三点一脉相承，printf()经常有重入和性能上的问题。如果你丢掉了第三和<br /><br />第四点，我不会太为难你的。不用说，如果你能得到后两点，那么你的被雇用前景越来越<br /><br />光明了。<br /><br />*****<br />代码例子（Code examples）<br /><br />12 . 下面的代码输出是什么，为什么？<br /><br />void foo(void)<br />{<br />unsigned int a = 6;<br />int b = -20;<br />(a+b &gt; 6) ? puts("&gt; 6") : puts("&lt;= 6");<br />}<br />这个问题测试你是否懂得C语言中的整数自动转换原则，我发现有些开发者懂得极少这些东<br /><br />西。不管如何，这无符号整型问题的答案是输出是 ”&gt;6”。原因是当表达式中存在有符号<br /><br />类型和无符号类型时所有的操作数都自动转换为无符号类型。 因此-20变成了一个非常大<br /><br />的正整数，所以该表达式计算出的结果大于6。这一点对于应当频繁用到无符号数据类型的<br /><br />嵌入式系统来说是丰常重要的。如果你答错了这个问题，你也就到了得不到这份工作的边<br /><br />缘。<br />13. 评价下面的代码片断：<br /><br />unsigned int zero = 0;<br />unsigned int compzero = 0xFFFF; <br />/*1's complement of zero */<br /><br />对于一个int型不是16位的处理器为说，上面的代码是不正确的。应编写如下：<br /><br />unsigned int compzero = ~0;<br /><br />这一问题真正能揭露出应试者是否懂得处理器字长的重要性。在我的经验里，好的嵌入式<br /><br />程序员非常准确地明白硬件的细节和它的局限，然而PC机程序往往把硬件作为一个无法避<br /><br />免的烦恼。<br />到了这个阶段，应试者或者完全垂头丧气了或者信心满满志在必得。如果显然应试者不是<br /><br />很好，那么这个测试就在这里结束了。但如果显然应试者做得不错，那么我就扔出下面的<br /><br />追加问题，这些问题是比较难的，我想仅仅非常优秀的应试者能做得不错。提出这些问题<br /><br />，我希望更多看到应试者应付问题的方法，而不是答案。不管如何，你就当是这个娱乐吧<br /><br />…<br /><br />动态内存分配（Dynamic memory allocation） <br />14. 尽管不像非嵌入式计算机那么常见，嵌入式系统还是有从堆（heap）中动态分配内存<br /><br />的过程的。那么嵌入式系统中，动态分配内存可能发生的问题是什么？<br />这里，我期望应试者能提到内存碎片，碎片收集的问题，变量的持行时间等等。这个主题<br /><br />已经在ESP杂志中被广泛地讨论过了（主要是 P.J. Plauger, 他的解释远远超过我这里能<br /><br />提到的任何解释），所有回过头看一下这些杂志吧！让应试者进入一种虚假的安全感觉后<br /><br />，我拿出这么一个小节目：<br />下面的代码片段的输出是什么，为什么？<br /><br />char *ptr;<br />if ((ptr = (char *)malloc(0)) == <br />NULL) <br />else<br />puts("Got a null pointer");<br />puts("Got a valid pointer");<br /><br />这是一个有趣的问题。最近在我的一个同事不经意把0值传给了函数malloc，得到了一个合<br /><br />法的指针之后，我才想到这个问题。这就是上面的代码，该代码的输出是“Got a valid <br /><br />pointer”。我用这个来开始讨论这样的一问题，看看被面试者是否想到库例程这样做是正<br /><br />确。得到正确的答案固然重要，但解决问题的方法和你做决定的基本原理更重要些。<br />Typedef <br /><font class="f006">: </font><br />15 Typedef 在C语言中频繁用以声明一个已经存在的数据类型的同义字。也可以用预处理<br /><br />器做类似的事。例如，思考一下下面的例子：<br /><br />#define dPS struct s *<br />typedef struct s * tPS;<br /><br />以上两种情况的意图都是要定义dPS 和 tPS 作为一个指向结构s指针。哪种方法更好呢？<br /><br />（如果有的话）为什么？<br />这是一个非常微妙的问题，任何人答对这个问题（正当的原因）是应当被恭喜的。答案是<br /><br />：typedef更好。思考下面的例子：<br /><br />dPS p1,p2;<br />tPS p3,p4;<br /><br />第一个扩展为<br /><br />struct s * p1, p2;<br /><br />.<br />上面的代码定义p1为一个指向结构的指，p2为一个实际的结构，这也许不是你想要的。第<br /><br />二个例子正确地定义了p3 和p4 两个指针。<br /><br />晦涩的语法<br /><br />16 . C语言同意一些令人震惊的结构,下面的结构是合法的吗，如果是它做些什么？<br /><br />int a = 5, b = 7, c;<br />c = a+++b;<br /><br />这个问题将做为这个测验的一个愉快的结尾。不管你相不相信，上面的例子是完全合乎语<br /><br />法的。问题是编译器如何处理它？水平不高的编译作者实际上会争论这个问题，根据最处<br /><br />理原则，编译器应当能处理尽可能所有合法的用法。因此，上面的代码被处理成：<br /><br />c = a++ + b;<br /><br />因此, 这段代码持行后a = 6, b = 7, c = 12。<br />如果你知道答案，或猜出正确答案，做得好。如果你不知道答案，我也不把这个当作问题<br /><br />。我发现这个问题的最大好处是这是一个关于代码编写风格，代码的可读性，代码的可修<br /><br />改性的好的话题。<br />好了，伙计们，你现在已经做完所有的测试了。<img src ="http://www.cnitblog.com/lainding/aggbug/13509.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-11 20:54 <a href="http://www.cnitblog.com/lainding/archive/2006/07/11/13509.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下的文字编辑器</title><link>http://www.cnitblog.com/lainding/archive/2006/07/11/13508.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Tue, 11 Jul 2006 12:38:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/11/13508.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13508.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/11/13508.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13508.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13508.html</trackback:ping><description><![CDATA[vi<br />pico<br />emacs<br /><img src ="http://www.cnitblog.com/lainding/aggbug/13508.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-11 20:38 <a href="http://www.cnitblog.com/lainding/archive/2006/07/11/13508.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>转换X Windows启动方式</title><link>http://www.cnitblog.com/lainding/archive/2006/07/11/13506.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Tue, 11 Jul 2006 11:12:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/11/13506.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13506.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/11/13506.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13506.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13506.html</trackback:ping><description><![CDATA[X Windows可以有多种启动方式，KDE、GNOME、FVWM、WINDOWMAKER。命令行下要启动X-Windows可以使用startx命令，但如果要转换不同的启动方式可以采用switchdesk命令来进行转换。<br /><img src ="http://www.cnitblog.com/lainding/aggbug/13506.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-11 19:12 <a href="http://www.cnitblog.com/lainding/archive/2006/07/11/13506.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>连接成功了</title><link>http://www.cnitblog.com/lainding/archive/2006/07/10/13477.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Mon, 10 Jul 2006 15:08:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/10/13477.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13477.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/10/13477.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13477.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13477.html</trackback:ping><description><![CDATA[第一步已经走出了，成功的通过文本方式连接到了Linux主机，前面未能连接的主要原因就在于没有打开Linux的Telnet服务和防火墙。<br />在通过Telnet方式连接到Linux的时候，出现了一个问题，是无法用root用户登录系统。这时只能重新建立一个用户来登录，然后通过su命令转换成root用户来进行root操作。这也许就像那篇文章中所说Telnet是通过明文传输密码，因而Linux不允许这样的访问。<br />然而采用Putty进行<a href="http://www.baidu.com/s?th=baidu&amp;cl=3&amp;word=%CA%B2%C3%B4%CA%C7SSH">SSH</a>(<font color="#ff0000">S</font>ecure <font color="#ff0000">Sh</font>ell)登录时可以成功的用root用户来进行登录。<br /><br />以上是我的第一点心得，如果能给访问我博客的朋友有所帮助将是非常高兴的。<br /><img src ="http://www.cnitblog.com/lainding/aggbug/13477.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-10 23:08 <a href="http://www.cnitblog.com/lainding/archive/2006/07/10/13477.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>无法从Windows下连接到那台Linux主机</title><link>http://www.cnitblog.com/lainding/archive/2006/07/10/13474.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Mon, 10 Jul 2006 14:43:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/10/13474.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13474.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/10/13474.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13474.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13474.html</trackback:ping><description><![CDATA[今天下午花了4个小时的时间，在实验室一台无人用的电脑上装了Red Hat Linux9.0。软件是很早以前下载的，我平日里很注意收集软件，可能就和别人喜欢收集古董一样吧，我也有收集的爱好，只不过是软件。装Linux的目的自然是为了进一步了解它。先前在自己用的电脑上用虚拟机安装了一个Linux，但由于要耗费系统资源，使得机器变慢，就在那台机器上单独装了一下。<br />但自己是希望通过Windows远程来访问那台Linux主机，自己也知道能行。但不知道如何才能访问。<br /><img src ="http://www.cnitblog.com/lainding/aggbug/13474.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-10 22:43 <a href="http://www.cnitblog.com/lainding/archive/2006/07/10/13474.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Linux下开启TELNET服务</title><link>http://www.cnitblog.com/lainding/archive/2006/07/10/13473.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Mon, 10 Jul 2006 14:39:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/10/13473.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13473.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/10/13473.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13473.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13473.html</trackback:ping><description><![CDATA[
		<span style="font-size: 13px;">
1。基础知识<br />
linux提供服务是由运行在后台的守护程序（daemon）来执行的。<br />
守护进程的工作就是打开1个端口（port），等待（listen）进入的连接。在C/S模式中，如果客户提请了1个连接，守护进程就创建（fork）子进程来响应这个连接，而父进程继续监听其他服务的请求。<br />
但是，对于系统所提供的每1个服务，如果都必须运行1个监听某个端口连接发生的守护程序，那么通常意味着系统资源的浪费。为此，引入“扩展的网络守护进程
服务程序”xinetd（xinetd internet daemon）。telnet服务也是由xinetd守护的。<br /><br />
2。检测telnet、telnet-server的rpm包是否安装<br />
OS：RedHat9<br /><br />
[root@localhost root]#rpm -qa telnet<br />
telnet-0.17-25<br />
//telnet*.rpm是默认安装的//<br />
[root@localhost root]#rpm -qa telnet-server<br />
空<br />
//telnet*.rpm是默认没有安装的//<br /><br />
3。安装telnet-server<br />
第3张盘上有telnet-server-0.17-25.i386.rpm<br />
[root@localhost root]#rpm -ivh telnet-server*.i386.rpm<br /><br />
4。修改telnet服务配置文件<br />
vi  /etc/xinetd.d/telnet <br />
service telnet<br />
{<br />
        disable         = yes<br />
        flags           = REUSE<br />
        socket_type = stream<br />
        wait            = no<br />
        user            = root<br />
        server          = /usr/sbin/in.telnetd<br />
        log_on_failure  += USERID<br />
}<br /><br />
将disable=yes行前加#，或者改为disable=no<br />
PS：<br />
安装telnet-server后，系统才有文件/usr/sbin/in.telnetd<br /><br />
5。重新启动xinetd守护进程<br />
由于telnet服务也是由xinetd守护的，所以安装完telnet-server，要启动telnet服务就必须重新启动xinetd<br />
[root@localhost root]#service xinetd restart<br />
或<br />
[root@localhost root]#/etc/init.d/xinetd restart<br /><br />
6。关闭系统的防火墙<br />
linux系统默认的防火墙是“high”<br /><br />
命令行界面CLI：<br />
[root@localhost root]# setup<br />
选择：“firewall configuration”<br />
选择：security level——“no firewall”<br /><br />
7。测试<br />
telnet IP<br /><br /><div class="smalltxt" style="margin-left: 2em; font-weight: bold;">QUOTE:</div><div class="altbg2" style="border: 1px solid rgb(105, 140, 195); margin: 3px 2em 2em; padding: 10px;">Red Hat Linux release 9 (Shrike)<br />
Kernel 2.4.20-8 on an i686<br />
login:</div>出现，就OK了！<br /><br />
8。telnet默认开机启动<br />
1）。命令ntsysv<br />
找到telnet，用空格键激活（*）服务<br />
2）。命令chkconfig<br />
chkconfig --add telnet<br />
chkconfig telnet on<br />
3）。图形用户界面GUI<br />
redhat-conhat-config-services<br />
或<br />
“主菜单”——“系统设置”——“服务器设置”——“服务”<br /><br /><br />PS：<br />
由于telnet登陆时是明文传送密码，所以不安全，建议使用ssh（secure shell）替代！<br />
windows下一般用F-Secure SSH ，putty SSH</span>
<img src ="http://www.cnitblog.com/lainding/aggbug/13473.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-10 22:39 <a href="http://www.cnitblog.com/lainding/archive/2006/07/10/13473.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最近想接触一下Linux</title><link>http://www.cnitblog.com/lainding/archive/2006/07/10/13472.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Mon, 10 Jul 2006 14:38:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/10/13472.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13472.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/10/13472.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13472.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13472.html</trackback:ping><description><![CDATA[很久以来一直想要接触一下Linux，可是也一直没能安心去看。这两天受到网上下载的一个Linux教程的影响，学习Linux的愿望特别强烈。决定好好和这个东西亲密接触一下。也为以后的工作打下一个好的基础。祝愿我的学习能有一个顺利的进展。<img src ="http://www.cnitblog.com/lainding/aggbug/13472.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-10 22:38 <a href="http://www.cnitblog.com/lainding/archive/2006/07/10/13472.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>vi的使用之汇总</title><link>http://www.cnitblog.com/lainding/archive/2006/07/10/13471.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Mon, 10 Jul 2006 14:21:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/10/13471.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13471.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/10/13471.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13471.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13471.html</trackback:ping><description><![CDATA[功能最强在的编辑器——vi<br /><p>vi是所有UNIX系统都会提供的屏幕编辑器，它提供了一个视窗设备，通过它可以编辑文件。当然，对UNIX系
统略有所知的人，或多或少都觉得vi超级难用，但vi是最基本的编辑器，所以希望读者能好好把它学起来，以后在UNIX世界里必将畅行无阻、游刃有余，因
为其他几种文本处理器并非UNIX标准配备。说不定别人的Linux机器没安装joe或pico，如果您不会vi，那您可能就没辄了。<br />vi的基本概念<br />基本上vi可分为三种操作状态，分别是命令模式（Command mode）、插入模式（Insert mode）和底线命令模式（Last line mode），各模式的功能区分如下：<br />1． Comand mode：控制屏幕光标的移动，字符或光标的删除，移动复制某区段及进入Insert mode下，或者到Last line mode。<br />2． Insert mode：唯有在Insert mode下，才可做文字数据输入，按Esc等可回到Comand mode。<br />3． Last line mode：将储存文件或离开编辑器，也可设置编辑环境，如寻找字符串、列出行号等。<br />不过可以把vi简化成两个模式，即是将Last line mode也算入Command mode,把vi分成Command 和Insert mode。<br />vi的基本操作<br />•进入vi<br />在系统提示符号输入vi及文件名称后，即可进入vi全屏幕编辑画面：<br />$ vi testfile<br />有一点要特别注意，就是您进入vi之后是处于“Command mode”下，您要切换到Insert mode才能输入文字。初次用vi的用户都会想先用上下左右键移动光标，结果电脑一直叫，把自己气个半死，所以进入vi后，先不要乱动，转换入Insert后再说。<br />•切换至Insert mode编辑文件<br />在Command mode下按‘i’、‘a’或‘o’三键就可进入Insert mode。这时候您就可以开始输入文字了。<br />i: 插入，从目前光标所在之处插入所输入的文字。<br />a: 增加，目前光标所在的下一个字开始输入文字。<br />o: 插入新的一行，从行首开始输入文字。<br />•Insert的切换→Command mode，按Esc键<br />您目前处于Insert mode，您就只能一直打字。假如您发现打错字了，想用光标键往回移动，将该字删除，就要按ESC键转换回Command mode，再删除文字。<br />•离开vi及存文件<br />在Command mode下，可按冒号“：”键入入Last line mode，例如：<br />:w filename (输入“w filename”，将文章存入指定的文件名filename)<br />:wq (输入“wq”，因为进入之时已经指定文件名testfile，所以会写入testfile并离开vi)<br />:q! (输入“q!”，强制离开并放弃编辑的文件)</p><p>Command mode功能键列表<br />在介绍command mode指令的时后，指令后面加上“常用”字眼的功能键，表示比较常用的vi指令，请读者您一定要学会、记住。<br />（1）I、a、o切换进入Insert mode。[超级常用]<br />（2）移动光标<br />vi可以直接用键盘上的光标键来上下左右移动，但正规的vi是用小写英文字母<br />h、j、k、l，分别控制光标左、下、上、右移一格。<br />按Ctrl+B：屏幕往后移动一页。[常用]<br />按Ctrl+F：屏幕往前移动一页。[常用]<br />按Ctrl+U：屏幕往后移动半页。<br />按Ctrl+D：屏幕往前移动半页。<br />按 0 （数字零）：移动文章的开头。[常用]<br />按 G：移动到文章的最后。[常用]<br />按 w：光标跳到下个word的开头。[常用]<br />按 e：光标跳到下个word的字尾。<br />按 b：光标回到上个word的开头。<br />按 $：移到光标所在行的行尾。[常用]<br />按 ^：移到该行第一个非空白的字符。<br />按 0：移到该行的开头位置。[常用]<br />按 #：移到该行的第#个位置，例：51、121。[常用]<br />（3）删除文字<br />x：每按一次删除光标所在位置的后面一个字符。[超常用]<br />#x：例如，6x 表删除光标所在位置的后面6个字符。[常用]<br />X：大字的X，每按一次删除光标所在位置的前面一个字符。<br />#X：例如，20X 表删除光标所在位置的前面20个字符。<br />dd：删除光标所在行。[超常用]<br />#dd：例如，6dd表删除从光标所在的该行往下数6行之文字。[常用]<br />（4）复制<br />yw：将光标所在处到字尾的字符复制到缓冲区中。<br />（想在和#x、#X的功能相反）<br />p：将缓冲区内的字符粘贴到光标所在位置（指令‘yw’与‘p必须搭配使用）。<br />yy：复制光标所在行。[超常用]<br />p：复制单行到您想粘贴之处。（指令‘yy’与‘p’必须搭配使用）<br />#yy：如：6yy表示拷贝从光标所在的该行往下数6行之文字。[常用]<br />p:复制多行到您想粘贴之处。（指令‘#yy’与‘p’必须搭配使用）<br />“ayy：将复制行放入buffer a, vi提供buffer功能，可将常用的数据存在buffer<br />“ap：将放在buffer a的数据粘贴。<br />“b3yy：将三行数据存入buffer b。<br />“b3p：将存在buffer b的资料粘贴<br />（5）取代<br />r: 取代光标所在处的字符：[常用]<br />R：取代字符直到按Esc为止。<br />（6）复原（undo）上一个指令<br />u：假如您误操作一个指令，可以马上按u，回复到上一个操作。[超常用]<br />.: .可以重复执行上一次的指令。<br />（7）更改<br />cw：更改光标所在处的字到字尾$处。<br />c#w：例如，c3w代表更改3个字。<br />（8）跳至指定行<br />Ctrl+G：列出光标所在行的行号。<br />#G：例如，15G，表示移动光标至文章的第15行行首。[常用]<br />Last line mode下指令简介<br />读者您要使用Last line mode之前，请记得先按Esc键确定您已经处于Command mode下后，再按冒号“：”或“/”或“？”三键的其中一键进入Last line mode。<br />1．列出行号<br />set nu: 输入“set nu”后，会在文章的每一行前面列出行号。<br />2．跳到文章的某一行<br />#：井号代表一个数字，在Last line mode提示符号“：”前输入数字，再按Enter就会跳到该行了，如：15[Enter]就会跳到文章的第15行。[常用]<br />3．寻找字符串<br />/关键字：先按/，再输入您想寻找的字，如果第一次找的关键字不是您相尽可能的，可以一直按n会往下寻找到您要的关键字为止。<br />？关键字：先按？，再输入您想寻找的字，如果第一次找的关键字不是您想要的，可以按n会往前寻找到您要的关键字为止。<br />4．取代字符串<br />1，$s/string/replae/g：在last line mode输入“1，$s/string/replace/g”会将全文的string字符串取代为replace字符串，其中1,$s就是指搜寻区间为文章从头至尾的意思，g则是表示全部取代不必确认。<br />%s/string/replace/c：同样会将全文的string字符串取代为replace字符串，和上面指令不同的地方是，%s和1,$s是相同的功能，c则是表示要替代之前必须再次确认是否取代。<br />1,20s/string/replace/g：将1至20行间的string替代为relpace字符串。<br />5．存文件<br />w：在last line mode提示符号“：”前按w即可将文件存起来。[超常用]<br />#，# w filename：如果您想摘取文章的某一段，存成另一个文件，可用这个指令#代表行号，例如30,50 w nice，将您正在编辑文章的第30~50行存成nice这个文件。<br />6．离开<br />q：按q就离开，有时如果无法离开vi，可搭配“！：强置离开vi，如“q！”<br />qw：一般建议离开时，搭配w一起使用，如此离开时还可存文件。[常用]</p><img src ="http://www.cnitblog.com/lainding/aggbug/13471.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-10 22:21 <a href="http://www.cnitblog.com/lainding/archive/2006/07/10/13471.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KeilC 与 Proteus连接调试</title><link>http://www.cnitblog.com/lainding/archive/2006/07/09/13433.html</link><dc:creator>陋石</dc:creator><author>陋石</author><pubDate>Sun, 09 Jul 2006 14:48:00 GMT</pubDate><guid>http://www.cnitblog.com/lainding/archive/2006/07/09/13433.html</guid><wfw:comment>http://www.cnitblog.com/lainding/comments/13433.html</wfw:comment><comments>http://www.cnitblog.com/lainding/archive/2006/07/09/13433.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cnitblog.com/lainding/comments/commentRss/13433.html</wfw:commentRss><trackback:ping>http://www.cnitblog.com/lainding/services/trackbacks/13433.html</trackback:ping><description><![CDATA[1、假若KeilC与Proteus均已正确安装在C:\Program Files的目录里，把C:\Program Files\Labcenter Electronics\Proteus 6 Professional\MODELS\VDM51.dll复制到C:\Program Files\keilC\C51\BIN目录中。
<br />2、用记事本打开C:\Program Files\keilC\C51\TOOLS.INI文件，在[C51]栏目下加入：
TDRV5=BIN\VDM51.DLL ("Proteus VSM Monitor-51 Driver")
其中“TDRV5”中的“5”要根据实际情况写，不要和原来的重复。
（步骤1和2只需在初次使用设置。）
<br />3、进入KeilC μVision2开发集成环境，创建一个新项目(Project)，并为该项目选定合适的单片机CPU器件（如：Atmel公司的AT89C51）。并为该项目加入KeilC源程序。
<br />4、单击“Project菜单/Options for Target”选项或者点击工具栏的“option for ta rget”按钮<img src="http://www.cnitblog.com/images/cnitblog_com/lainding/Tech/image070.jpg" alt="image070.jpg" border="0" height="17" width="20" />，弹出窗口，点击“Debug”按钮，出现如图所示页面。<br /><img src="http://www.cnitblog.com/images/cnitblog_com/lainding/Tech/image072.jpg" alt="image072.jpg" border="0" height="309" width="462" /><br />在出现的对话框里在右栏上部的下拉菜单里选中“Proteus VSM Monitor一51 Driver”。并且还要点击一下“Use”前面表明选中的小圆点。
再点击“Setting”按钮，设置通信接口，在“Host”后面添上“127.0.0.1”，如果使用的不是同一台电脑，则需要在这里添上另一台电脑的IP地址(另一台电脑也应安装Proteus)。在“Port”后面添加“8000”。设置好的情形如图所示，点击“OK”按钮即可。<br /><img src="http://www.cnitblog.com/images/cnitblog_com/lainding/Tech/image074.jpg" alt="image074.jpg" border="0" height="124" width="300" /><br />最后将工程编译，进入调试状态，并运行。<br />5、Proteus的设置
进入Proteus的ISIS，鼠标左键点击菜单“Debug”， 选中“use romote debuger monitor”，如图所示。<br /><img src="http://www.cnitblog.com/images/cnitblog_com/lainding/Tech/image076.jpg" alt="image076.jpg" border="0" height="230" width="171" /><br />此后，便可实现KeilC与Proteus连接调试。

<br />6、KeilC与Proteus连接仿真调试
单击仿真运行开始按钮 ，我们能清楚地观察到每一个引脚的电频变化，红色代表高电频，蓝色代表低电频。
<img src ="http://www.cnitblog.com/lainding/aggbug/13433.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cnitblog.com/lainding/" target="_blank">陋石</a> 2006-07-09 22:48 <a href="http://www.cnitblog.com/lainding/archive/2006/07/09/13433.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>