资讯详情

C/C++程序员工作面试的秘密

了解一点硬件知识是非常危险的。一名程序员拆下一张新颖的圣诞卡,拿出压电乐芯片。他偷偷地把它安装在老板的键盘上,并连接到一个发光的二极管上。他测试了一个能发光二极管的电压,足以驱动其中一个芯片。

然后,我(哦!错了,我指的是程序员)修改了系统编辑器,当它启动时点亮发光二极管,当它退出时关闭发光二极管。结果:只要老板使用这个编辑器,他的终端就会继续演奏圣诞颂歌!半小时后,隔壁办公室的人们非常愤怒,迫使老板停止工作,直到发现事故的原因。

——The Second Official Handbook of Practical Jokes

A.1 硅谷程序员面试

本附录提供了C程序员在顶级公司寻找职位的面试提示。尖端计算机行业最值得称道的事情之一就是选择新员工加入团队。在许多行业,管理者或经理完全负责员工的录取,但事实上,只有他自己才能满足他提出的申请条件。然而,在软件开发的前沿领域,特别是当高科技企业刚刚开始时,程序员往往比决定哪个候选人是最好的个人申请人的经理更有资格说。很少有天才程序员需要做一些系统开发,对他的要求也特别具体。所以有时候技术能力是你面试工作时唯一重要的专业。

因此,程序员面试形成了一种非常独特的风格。根据公司的策略,经理在众多面试官中寻找人才。预计入围者将进行严格的技术评估,评估者是开发团队的每个人,而不仅仅是经理。典型的工作面试将持续一整天,包括与六七名不同的工程师进行大约一个小时的会谈——他必须说服每个人都有能力加入开发团队,以获得工作承诺。

工程师经常会有一些他们最喜欢的问题,本章包含了一些工程师喜欢的问题。泄露这些秘密是无害的——一个读过这本书的程序员可能有足够的知识加入一家优秀的软件公司。这些问题中的许多来自于我们尝试编程的真实算法,现在已经被其他人用新的问题所取代。当然,当你面试候选人时,你不仅关注他们对问题的反应,还关心他们如何反应。他们是深思熟虑一个问题,提出几种可能性,还是一有想法就脱口而出?他们在解释自己的想法时提到的论据是否足够有说服力?他们是对明显错误的策略固执己见,还是思维灵活,很快提高答案?下面的一些问题产生了最奇怪的答案。你可以自己试验一下,掂量一下自己的份量!

A.2 如何检测链表中的循环?

这个问题看起来很简单,如何检测链表中的循环?但提问者不断对问题施加一些额外的限制,使问题很快变得凶猛。

标记访问过的每个元素,并继续遍历链表。如果遇到已经标记的元素,说明链表有循环。

这个链表位于只读内存区域,无法在元素上作标记。

当访问每个元素时,将其存储在一个数组中。检查每个后续元素,看看它是否存在于数组中。有时,一些可怜的程序员会纠结于如何使用散列表来优化数组访问的细节,结果是壳。

哦!内存空间非常有限,无法创建足够长的数组。然而,假设链表中有循环,它出现在前N个元素中。

(如果程序员能达到这一步):

指向链表头部设置指针。在接下来的访问中,直到第n个元素N-一个元素依次与指针指向的元素进行比较。然后指针移动到第二个元素,与后面一起使用N-比较两个元素。根据这种方法依次进行比较。如果有相等的情况,说明前N个元素有循环。否则,如果所有N个元素都不相等,说明链表中没有循环。

哦!不!链表的长度是任意的,循环可能会出现在任何位置。(即使是优秀的候选人也会在这关碰壁)

首先,排除一种特殊的情况,就是3个元素的链表中第2个元素的后面是第1个元素。设置两个指针p1和p2,p指向第一个元素,p指向第三个元素,看它们是否相等。若相等属于上述特殊情况。假如不等,把p向后移动一个元素,p两个元素向后移动。检查两个指针的值,如果相等,则表示链表中有循环。若不相等,继续遵循上述方法。如果有两个指针,NULL表明链表中没有循环。如果链表中有循环,这种方法肯定能检测到,因为其中一个指针肯定能赶上另一个指针(两个指针有相同的值),虽然可能需要几次遍历才能检测到链表。

这个问题还有其他答案,但上面提到的几个是最常见的。

A.3 C语言中不同增值句有什么区别?

考虑以下四个句子:

  x = x   1;      /* 正规形式 */     x;           /* 前缀自增 */   x  ;           /* 后缀自增 */   x  = 1;         /* 复合赋值 */

显然,这四个句子的功能是相等的,它们都增加了x的值1。如果不考虑前后的上下文环境,就没有区别。为了回答这个问题,找出这四个句子之间的区别,考生需要(隐式或显式)提供适当的上下文环境。注意最后一句话是算法语言中的一种表达x方便方法等于x加1。因此,这个句子仅供参考,我们需要寻找的是其他三个句子的独特性。

大多数C程序员可以立即指出 x是一种前缀自增,当它先增加x的值,然后在周围的表达式中使用x的值。而x 它是一种后缀自增,先在周围表达式中使用x值,再增加x值。有人认为C语言存在 操作符和-的唯一原因是*p 在PDP-一个单一的机器指令可以表示在机器上。事实并非如此。这一特征继承了PDP-7上的B语言,但自增自减操作符在所有硬件系统中的广泛应用令人难以置信。

有些程序员在这里没有深入考虑,忽略了当x不是一个简单的变量,而是一个涉及数组的表达式时,就像x = 这种形式非常有用。如果你有一个复杂的数组引用,并且需要证明同样的下标形式可以用于两种引用,那么

node[i>>3]  = -(0x01 << ( i & 0x7));

这是你应该采用的方法。这个例子是我直接从操作系统的代码中取出的,只有数据名称被更改(为了保密)。优秀的候选人也可以指出左值(定位对象的表达式编译语言——通常有一个地址,但它也可能是一个寄存器,或地址或寄存器加一个位置)只计算一次。这一点非常重要,因为以下陈述:

mango[i  ]  = y;

被当作

mango[i] = mango[i]   y; i  ;

而不是

mango[i  ] = mango[i  ]   y;

过去,当我们申请一些申请时,Sun的Pascal编译器队伍的位置的候选人进行面试时,最好的那位候选人(他最终获得了这个工作——嗨!Arindam)这些差异与编译器的中间代码有关,例如 x取x地址,添加其内容,然后将值放入寄存器中;x 取x地址,将其值放入寄存器中,然后增加内存中的x值。对了,用编译器的术语,另外两句话该怎么描述?

尽管Kernighan和Ritchie认为自增操作比直接加1更有效率(K&R2, 第18页),但目前使用的当代编译器在这方面通常做得很好,使这些方法的速度相同。现代C编译器在编译这些句子时,如果没有相关的上下文环境可以显示它们之间的子时应该产生相同的指令。它们应该是增加一个变量时最快的一种指令。这些代码可以在你喜欢的编译器上编译,编译器应该有一个选项,可以生成汇编指令列表。您还可以将编译器设置为调试模式,这通常使检查相应的C语句和汇编指令更容易。不要使用优化选项,因为这些句子可能会因为优化而被简化。在Sun在工作站,附上魔咒-S使命令行看起来如下:

cc –S –Xc banana.c

这个-S选项使编译停止汇编阶段,输出汇编语言指令banana.s文件中。最新的编译器SPARCompilers 3.0进行了改进,当使用此选项时,它可以在汇编程序输出文件中分散源代码。这使得更容易找到问题并生成诊断代码。

-Xc选项告诉编译器拒绝任何不符合要求ANSI C编写新代码时始终使用这个选项是个好主意,因为它有助于程序获得最大程度的可移植性。

所以有时候区别在于哪个在源代码上看起来更好。一般较短的形式较长的形式更容易阅读。然而,过度简洁也会使代码难以阅读(只要问问那些试图修改别人的人APL代码的人就知道了)。当我还是系统编程研究生班的助教时,一个学生让我看一些代码。他说代码中有一个未知的代码Bug,但是由于代码过于紧凑,所以无法把它找出来。在一些高年级C程序员的嘲笑中,我们系统地将以下单行代码相似:

frotz[--j   i  ]  = --y;

扩展为功能相同但长度更长的:

--y; --j; frotz[j i] = frotz[j i]   y; i  ;

这让喜欢玩耍技巧的程序员感到恼火。用这种方法,我们突然发现其中一个操作位置是错误的。>

这种做法并不能使编译器产生的代码更有效率,而且会使你丧失调试代码的机会。正如Kernighan和Plauger所指出的那样,“人人都知道调试比第一次编写代码要难上一倍。所以如果在编写代码时把自己的聪明发挥到极致,那么在调试时又该怎么办呢?”[2]

A.4 库函数调用和系统调用区别何在

有一个问题我们时常用来考察候选人是否知道他编程的方法是否简单,“库函数调用和系统调用的区别何在?”令人惊奇的是,许多人从来没有想过这个问题。我们并不曾见到许多描述这个区别的书籍,所以这是个很好的问题,可以判断候选人是否具有丰富的编程经验以及是否具有找出这类问题的答案的敏锐感觉。

简明的回答是函数库调用是语言或应用程序的一部分,而系统调用是操作系统的一部分。你要确保弄懂“trap(自陷)”这个关键字的含义。系统调用是在操作系统内核发现一个“trap”或中断后进行的。这个问题的完整答案需要覆盖表A-1中列出的所有要点。

 

库函数调用通常比行内展开的代码慢,因为它需要付出函数调用的开销。但系统调用比库函数调用还要慢很多,因为它需要把上下文环境切换到内核模式。在SPARC工作站上,我们对一个库函数调用进行记时(就是一个过程调用的速度),结果大约是半微秒。系统调用所需要的时间大约是库函数调用的70倍(35微秒)。纯粹从性能上考虑,你应该尽可能地减少系统调用的数量。但是,你必须记住,许多C函数库中的程序通过系统调用来实现功能。最后,那些相信麦田里的怪圈的人们会对system()函数实际上是一个库函数这个概念感到困惑。

A.5 文件描述符与文件指针有何不同

这个问题是前面一个问题的自然延续。所有操纵文件的UNIX程序或者使用文件指针,或者使用文件描述符来标识它们正在操作的文件。它们是什么?什么时候应该使用?事实上答案非常直截了当,它取决于你对UNIX I/O的熟悉程度以及对各种因素利弊的权衡。

所有操纵文件的系统调用都接受一个文件描述符作为参数,或者把它作为返回值返回。“文件描述符”这个名字多少显得有点命名不当。在Sun的编译器中,文件描述符是一个小整数(通常在0-255之间),用于索引开放文件的每个进程表(per-process table-of-open-files)。系统I/O调用有creat(), open(), read(), write(), close(), ioctl()等,但它们不是ANSI C的一部分,不会存在于非UNIX环境。如果你使用了它们,你的程序将失去可移植性。因此,建立一组标准I/O库调用是必要的,ANSI C现在规定所有的编译环境都必须支持它们。

为了确保程序的可移植性,应该使用标准I/O库调用,如fopen(), fclose(), putc(), fssek()等——它们中的绝大多数名字中带有一个“f”。这些调用都接受一个类型为指向FILE结构的指针(有时称为流指针)的参数。FILE指针指向一个流结构,它在<stdio.h>中定义。结构的内容根据不同的编译器有所不同,在UNIX中通常是开放文件的每个进程表的一个条目。在典型情况下,它包含了流缓冲区、所有用于提示缓冲区中有多少字节是实际的文件数据的变量以及提示流状态的标志(如ERROR和EOF)等。

  • 所以,文件描述符就是开放文件的每个进程表的一个偏移量(如“3”)。它用于UNIX系统调用中,用于标识文件。
  • FILE指针保存了一个FILE结构的地址。FILE结构用于表示开放的I/O流(如hex 20938)。它用于ANSI C标准I/O库调用中,用于标识文件。

C库函数fdopen()可以用于创建一个新的FILE结构,并把它与一个确定的文件描述符相关联(可以有效地在文件描述符小整数和对应的流指针间进行转换,虽然它并不在开放文件表中产生一个额外的新条目)。

A.6 编写一些代码,确定一个变量是有符号数还是无符号数

有一位同事在接受Microsoft面试时,其中一个题目就是“编写一些代码,确定一个变量是有符号数还是无符号数”。这实际上是一个相当难的问题,因为它留下了太多的空间让你去理解这个问题。有些人错误地把“有符号数”同“具有负号”等同起来,以为这个问题只需要一个小小的函数或宏,测试变量的值是否小于零就可以了。

问题自然没有这么简单。要回答这个问题,你必须在特定的编译器中确定一个给定的类型是有符号数还是无符号数。在ANSI C中,“char”既可以是有符号数,也可以是无符号数,这是由编译器决定的。当你编写的代码需要移植到多个平台时,知道类型是不是有符号数就非常有用了,如果该类型在所有的编译器编译时都是恒定的,那就再理想不过了。

你无法用函数实现目的。函数形式参数的类型是在函数内部定义的,所以它无法穿越调用这一关。因此,你必须编写一个宏,根据参数的声明对它进行处理。

接下来就是区别宏的参数到底是一个类型还是一个类型的值。假定参数是一个值,无符号数的本质特征是它永远不会是负的,有符号数的本质特征是对最左边一个位取补将会改变它的符号(比如2的补码表示,它肯定是个负数)。由于作为参数的这个值的其它位与这个测试无关,你可以对它们全部取补,结果是一样的。因此,可以像下面这样尝试:

#define ISUNSIGNED(a)  (a >=0 && ~a >= 0)

如果宏的参数是一个类型,其中一个方法是使用类型转换:

#define ISUNSIGNED(type) ((type)0 – 1 > 0)

面试的关键就在于正确理解问题!你需要仔细地听,如果不理解问题或者觉得它的定义不清,可以要求一个更好的解释。第一个代码例子只适用于K&R C,新的类型提升规则导致它无法适用于ANSI C。练习:解释一下为什么,并提供一个适用于ANSI C的解决方案。

Microsoft的绝大部分问题都想考察你在压力下能够怎样思考问题,但它们并不都是技术性的。一个典型的非技术性问题可能是“美国一共有多少个加油站?”或“美国一共有多少个理发店?”他们想看看你是否作出正确的猜测和估计,或者能够提供一种寻找更可靠答案的好方法。建议:打电话给各个州的执照发放机构,只要50个电话,你就可以获得准确的数字。或者,你也可以选六七个有代表性的州,根据样本推断出总体数量。你甚至可以像一位环保主义者那样回答,当被问及“美国有多少个加油站时”时,她生气地回答:“太多了!”

A.7 打印一棵二叉树的值的时间复杂度是多少

这个问题是面试者在申请Intel编译器小组的一个职位时被问到的。现在,关于复杂度理论首先需要知道的是大O表示法。O(N)表示当N(通常是需要处理的对象数量)增长时,处理时间几乎是按照线性增长的。类似,O(N2)表示当N增长时,处理时间的增长要快得多,大致是按照N的平方增长的。关于复杂度理论你其次需要知道的是在一棵二叉树中,所有的操作的时间复杂度都是O(log(n))。所以,很多程序员不假思索地作出了这个回答。错误!

这个问题有点类似于Dan Rather著名的“频率是什么?Kenneth”问题——这个问题用于干扰、混淆和激怒对方而不是真的向对方咨询信息。要打印一棵二叉树所有结点的值,你必须对它们逐个访问,所以时间复杂度为O(N)。

我的一些同事在接受惠普公司电子工程师职位的面试时,也遇到了类似的陷阱问题。这个问题是:在一个理想的没有阻抗的电路中,一个充了电的电容器和一个未充电的电容器突然接触在一起时,会发生什么情况?机械工程师职位的面试题则是两根质量忽略不计的弹簧从平衡位置拉紧,然后松开会发生什么?主考官分别运用两个不同的物理定理 (如电容器例子中电荷守恒定理和能量守恒定理) 推导出两个不同的结论,然后他询问面试者为什么会出现两种不同的结果?原因何在?

这里的陷阱在于主考官至少在表达其中一个结论时使用了一个割裂了初始条件和结束条件的积分公式。在现实世界中,这确实没错,但在理论性的实验上,它导致了对不连续状态的积分(因为减速效果被理想化了)。这样,这个公式不再适用。工程师很可能以前从来没有碰到过这类问题。但是,这些类似无质量弹簧和无阻抗电路的问题每次当你遇上时都会使你难堪!

但是,应试者在申请一家大型管理咨询公司的一个软件顾问职位时,主考官又抛出了另一个弧线球,问题是“如果execve系统调用成功,它将返回什么?”回顾一下,execve()函数用参数中的可执行文件替换调用者进程的映像并开始执行。所以,当execve系统调用成功执行后,它并不会返回一个值。把这些陷阱问题用于刁难你的朋友确实很有趣,但如果在面试中遇到它们就不太有趣了。

A.8 从文件中随机提取一个字符串

这也是Microsoft喜欢使用的问题之一。主考官要求面试者编写一些代码,实现从一个文件(文件的内容是许多字符串)中随机提取一个字符串。解决这个问题经典的方法是读取文件,对字符串进行计数,并记录每个字符串的偏移位置。然后,在1和字符串总数之间取一个随机数,根据选中字符串的偏移位置取出该字符串。

但是,主考官设置了一些条件,使这个问题的难度大大增加。他要求只能按顺序遍历文件一次,并且不能使用表格来存储所有字符串的偏移位置。对于这个问题,主考官的主要兴趣在于你如何解决问题的过程。如果你提问,他会给你一些提示,所以大多数面试者最终都能获得答案。主考官对你的满意程度取决于你获得答案的速度。

基本的技巧是在幸存的字符串中挑选,并在过程中不断更新。从计算的角度看这个方法是非常低效的,所以它很容易被忽略。你打开文件并保存第一个字符串,此时就有了一个备选字符串,并有100%的可能性选中它。保存这个字符串,继续读入下一个字符串,这样就有了两个备选字符串,选中每个的可能性都是50%。选中其中之一并保存,然后丢弃另一个。再读入下一个字符串,按照新字符串33%原先幸存的字符串67%的概率(它代表前两个字符串的幸存者),在两者之间选择一个,然后保存新选中的字符串。

根据这个方法,依次对整个文件进行处理。在其中每一步,读入字符串N,在它(按照1/N的概率)和前一个幸存的字符串(按照N-1/N的概率)之间进行选择。当到达文件末尾的时候,最后一个幸存的字符串就是从整个文件中随机提取的那个字符串!

这是一个非常艰难的问题,你要么依靠尽可能少的提示获得答案,要么就预先做好充分准备,提前阅读本书。

A.9 轻松一下——如何用气压计测量建筑物的高度

我们觉得这些问题乐趣无穷,甚至还把它们应用到自己的非计算机环境中。Sun有一个叫“junk mail”的e-mail账号,让员工们共享偶然兴之所致得到的灵感。有时候,人们把问题放到这个账号中,并要求其它工程师进行比赛,提交最佳答案。这里就有这样一个难题,它是最近才放上去的。

有一个很早的故事,讲的是一位物理系学生寻找新奇的方法用气压计测量一幢建筑物的高度。Alexander Calandrain在The Teaching of Elementary Science and Mathematics[4]中引述了这个故事。

一位学生考试被判不及格,因为他拒绝使用班上老师所教的方法回答问题。当这名学生提出抗议时,学校指定我担任仲裁人。我来到教授的办公室,阅读了考试题:“怎样在气压计的帮助下测量一幢高楼的高度。”

这位学生是这样回答的:“把气压计带到楼顶,用一个长绳系住。把气压计放低,直到触及街面,然后再提起来,测量绳子的长度。绳子的长度就是建筑物的高度。”

高分的回答应该是充分运用物理学的原理,但这个回答显然没说明这一点。我提议给这位学生另一次机会回答这个问题。我给了这位学生6分钟时间,并警告他答案必须与物理学的知识有关。结果他只用了一分钟就交上了答案:“把气压计带到楼顶,倚在屋顶的边缘上,然后放开气压计,并用秒表进行计时。然后,运用物体下坠公式:S=1/2 a t2计算建筑物的高度。”此时,我毫不犹豫地给了这位学生满分。

这位学生继续说出了3种运用气压计测量建筑物高度的方法:

在阳光灿烂的日子里,测量气压计的高度、气压计影子的高度以及建筑物影子的高度,然后运用简单的比例原理,计算出建筑物的高度。

带上气压计走上建筑物的楼梯。当你爬楼梯时,用气压计的高度在墙上作标记。到达楼顶后,数一下标记的数量,你就可以得到以气压计高度为单位的建筑物高度。

最后一种方法(也许最不可行)是把气压计送给建筑物的管理员,让他告诉你建筑物的高度。

当这个老掉牙的故事作为一个“科学难题”出现在Sun时,人们又重新激起了对它的热情,总共提出了16种新的用气压计测量建筑物高度的好方法。这些方法如下:

:分别测量楼顶和楼底的气压,然后根据气压差计算大楼的高度。这个方法是这个问题最初设计时的标准答案,也是测量大楼高度最不精确的方法之一。

:来到建筑物的顶部,用绳子系住气压计,把它放低到地面。然后晃动气压计,测量钟摆的摆动时间,根据摆动时间可以计算出钟摆的长度,也就是建筑物的高度。

:把气压计当掉,换取一点种子基金。然后用连信方法(或称神秘链方法)积累一大笔钱,把这笔钱堆得和大楼一样高,然后根据每张纸币的厚度和纸币的张数计算大楼的高度。这个方法并没有提及如何在警察闻讯赶来之前完成对大楼的测量。

:用气压计作为武器,威逼大楼的管理员说出大楼的高度。

:在地面上用一架迫击炮把气压计送上半空,让它正好到达楼顶的高度。你可能需要进行几次距离修正发射以获得刚好能把气压计送到大楼高度的发射方法。运用标准弹道计算表,你可以计算出这次弹道发射的高度,也就是大楼的高度。

:把气压计作为镇纸压在建筑物设计图纸上,然后从图纸上找出建筑物的高度。

:从大楼的顶部把气压计扔下来,测量气压计撞击地面和你听到撞击声的时间差。在实际可行的距离内,视觉传递的时间可以忽略不计,而声音的传递速度(在标准温度和气压条件下是340m/s)是已知的,根据上面这些数据可以计算出大楼的高度。

:把气压计的玻璃面作为镜子,测量镜面反射亮光从楼顶到地面的来回时间,由于光的速度是一个已知量,所以大楼的高度也可以据此测出。

:卖掉气压计,用这笔钱买一些适当的仪器测量大楼的高度。

:用一根绳子系住气压计,把绳子绕在一个小型发电机的轴上。然后把气压计从大楼顶上扔下来,绳子就会使发电机转动。测量气压计从楼顶掉到地面期间发电机所发的电。发电机产生的电能和轴旋转的圈数是成正比的,根据这些数据可以算出楼顶到地面的高度。

:在地面上选一点,它和大楼的距离是已知的。带上气压计和一个量角器来到大楼的顶部,等待太阳到达水平线。然后,把气压计当作镜子,把一束日光引到先前所设定的地点,用量角器测量气压计的角度,然后用三角学原理计算大楼的高度。

:测量气压计的高度。叫一个朋友,并带上一把卷尺。趴在大楼外已知距离的一点,气压计放在你和大楼之间,调整气压计的位置,从你看上去气压计上端正好与楼顶相平。

然后叫你的朋友测量你的眼睛距离气压计的距离,最后根据比例原理计算出大楼的高度。

:从大楼外已知距离的地点支起三角架,架上是照相机。然后把气压计放在与照相机距离已知的地方,拍下照片。根据照片中气压计和大楼的相对高度,你可以计算出大楼的实际高度。

:用长绳系住气压计,从大楼上挂下来直到地面。测量钟摆的摆动时间,根据重力加速度的差别计算出大楼的高度。

:在大楼的顶部和底部分别用弹簧秤测量气压计的重量(不能用天平秤),两个重量应该有所差别,这是由于重力加速度的差异引起的。(一位读者告诉我Lacoste Romberg重力计能够提供准确结果所需要的精度)你可以根据这两个读数计算出大楼的高度。

:把气压计从楼顶扔下来,掉到地面一个装有水的容器里。容器的开口应尽量小,尽可能防止水的溅出。水温的升高是气压计的机械能转换为热能的结果,根据水温升高的度数可以计算出气压计到达地面的势能,进一步可以计算出大楼的高度。

你是不是认为这样的问题只会在代数学里出现。

 

C代码。C代码运行。运行码运行…请! ——Barbara Ling 所有的C程序都做同一件事,观察一个字符,然后啥也不干。 ——Peter Weinberger

《C专家编程》展示了最优秀的C程序员所使用的编码技巧,并专门开辟了一章对C++的基础知识进行了介绍。

书中C的历史、语言特性、声明、数组、指针、链接、运行时、内存以及如何进一步学习C++等问题进行了细致的讲解和深入的分析。全书撷取几十个实例进行讲解,对C程序员具有非常高的实用价值。

本书可以帮助有一定经验的C程序员成为C编程方面的专家,对于具备相当的C语言基础的程序员,本书可以帮助他们站在C的高度了解和学习C++。

标签: 二极管dan217

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台