











http://bbs.yingjiesheng.com/thread-15033-1-1.html
今天應該是畢業找工作生涯的最后一次面試了,發個筆經面經,為后來人
鋪路.我面的是Radio Network Planning。
筆試:海選,通過chinahr出的一組能力測試題篩選。好像篩了不少人。
題目包括詞語填空,閱讀理解,圖形,數字題,基本數學題,表格題。
一面:面試官為應聘職位的部門經理?;旧蠟橹形模虚g可能抓住項目的
某個部分突擊一下英文。面試官很和藹,不用緊張。
問的內容涉及:個人介紹,項目介紹,然后抓住關心的項目問細節問題。
做過的項目很match的話,問的會更詳細一些。然后問,項目中碰到的最
大困難是什么?怎么應對的?優勢,缺點,舉例說明一下?三個詞形容
一下自己。然后,被面者問面試官問題。
二面:二面是nokia請專業人員做的人力測評,大概要多半天的時間。主要看個
人特點和潛力。改專業人員會把測評結果提交給部門經理,輔助經理做
決定。網上有比較多的面經,講的也很詳細。流程大致如下:
1)7個人小組活動:構建一個太空站的項目,給了太空站的地圖和項目介紹,要求
說服董事會投資和盈利。黑板上寫好了每個人的拼音名字,所以也沒有進行個人介
紹,然后hr用英文介紹了一下我們下面project主要的任務,給了10分鐘的時間想,并且
期間可以提問。然后30分鐘時間group討論和實現。在整個過程中一半中文,一半英文。
這個時候會有人記錄你的表現,后來我知道他們不是要你表現的最優秀,但是要有grou
p spirit,能夠接受他人的意見和提出自己的見解。討論結束以后,group可以任意方式
做中英文綜述,接著hr會要求你給給自己打一個分數,然后問你為什么這樣打分。
2)邏輯能力測評:24道圖形題,15分鐘做完。
3)午飯。
4)性格測試:300多道題,對一句話的描述回答true or false。
5)一組問卷:你的優點缺點,職業規劃,等
6)Interview:問了我是否有看到網上的面經,有什么幫助?
剛才的表現中為什么會想到哪些?
自己選一個項目說明自己是怎么工作的?由于我說的那個項目中我是項目 某小組的組長,就問到我是如何帶領團隊工作的?這個問了比較多。
你的職業規劃是怎么樣的?
提問。
7)Over。
本貼地址:http://bbs.yingjiesheng.com/thread-15033-1-1.html
筆試:
電路,自控,機械,net,c#,結構表,英文翻譯……
這還不算啥,最后一頁才搞笑。
請書寫無機和有機化學方程式各一個。
牛頓三大定律,熱力學三大定律
……
面試:
job hunting(2)之NokiA Nokia一直是很牛b的,從9月開始就收簡歷,折騰到了12月,歷時2個半月之久。
第一次收到電話面試,正在上班,覺得十分尷尬,跑到外面在門衛面前表現了半個小時的英語,估計他都以為我有病,話都說不明白。
實現一點沒有準備,就被Nokia給突擊了,事后我一直想,簡歷一定要做好,絕不能再犯類似錯誤,我竟然寫了C++項目經驗比C時間還長,讓面試的gg抓住了不放,非要問個一二三。
還是慶幸那段時間還在看friends,對英語的基本感覺還在,沒有生疏,順利通過了電話面試。接下來的技術筆試,復試,都沒有懸念的通過了,nokia還是比較正式的,就是戰線拉的太長了,后來因為簽了其它公司,就沒有參加最后一次hr面試。
一直以來,我在bbs上是屬于潛水者一型的,接到nokia的offer也有一段時間了。忽然就很有點感觸。很想寫出來和大家分享一下我的面試,希望能夠給下一屆的同學們一點參考。前面也有一些關于nokia面試的文章,我看了一下,和我的面試情況基本相同。我就不重復說了,把我在面試中覺得應該注意的地方寫一下吧。
1,第一面的時候主要是考你的base knowledge,筆試完三頁紙的技術問題以后(我當時考的主要是基本的通訊知識和GSM的基本概念),部門的manager就會問你一些技術問題,如果你有項目經驗的話,也會大概問一些,但是沒有深入(這個很重要,其實他在第一面以后就會對你的個人經歷有一個初步認識,以后的面試也是基本上圍繞這些問題展開。)整個過程很輕松,大概面試30分鐘左右,然后他會通知你回去等消息。
2,老實說來,我就經過兩次面試就接到錄用通知了,因為nokia的第二次面試安排的很緊湊,基本上是整整一天。第二次面試我是到異地去面試的,nokia之類的外企如果通知你去外地面試是一定會報銷路費和三星級以上(nokia指定)酒店的住宿費的。等我到了公司以后,發現我們是安排一個group一起面試的。當時我們那個group是6個人,聽說也有8個的。等大家到齊了,我們被安排到一個小房間做一個“構建動物園”的project,這個project還蠻重要的,hr,部門manager和老總(一個荷蘭老外,很象圣誕老人)都來了,黑板上寫好了每個人的拼音名字,所以也沒有進行個人介紹,然后hr用英文介紹了一下我們下面project主要的任務,給了5分鐘的時間想,然后15分鐘時間group討論和實現。在整個過程中可以用中文,這個時候會有人記錄你的表現,后來我知道他們不是要你表現的最優秀,但是要有group spirit,能夠接受他人的意見和提出自己的見解。
討論結束以后,group推薦一個人出來做中英文綜述,當時我們組是推薦了一個女生講的,都是她一個人講(呵呵,后來聽別的組說他們是推薦一個人用英文,一個人用中文),我當時忽然很膽怯,事實上英語也沒有那么牛,所以基本上沒有說什么。接著hr會要求你給整個group打出一個分數,給自己打一個分數,然后說你為什么這樣打分。我們那組出了一個意外,第一個站起來回答的dd居然給每個人都打了分數,我在極度驚訝之下,也飛快的給每個人打了分數。后來問到我時,我說了我的分數,我給自己打的分數比group分數高,事實上只有我一個人這樣打了,hr很奇怪的問我,為什么我覺得自己的表現很好?
我當時特別的窘迫,想了一下我說我覺得自己能夠積極主動的說出自己的想法,能夠接納他人的建議,而且給group打分和給自己打分不是基于同一個評判標準的。所以建議ddmm們以后如果要打分一定要想好為什么要給自己打這樣的分數?;旧?,nokia的面試官都會特別的客氣,不會咄咄逼人,但是如果你自己要準確的給自己定一個位。現在想起來還是覺得當時好丟人阿。。。。。后來我們很驚訝的發現,那個表現最好的mm沒有錄取,很可惜,不過這也能夠看出來,nokia不是要求你能夠表現多出色,它要的合適的人,所以面試的時候不要有壓力,如果是你的,一定會是你的。
3,午餐,nokia請客,好豐盛的KFC大餐,不過大家好像都沒有什么胃口,大家都在相互聊天和分享公司信息。
4,下午的時候就發了一堆的考卷,有365題的人格測試題,好像是要劃出一個曲線看看和公司要求的人才符合不符合,總之你要盡量表現得樂觀就對了,他們很看重這個。那個人格測試題,特別的搞笑,還有造句題,for example,我認為女人——————————。我當時的答案是我認為女人應該獨立自主。大家的答案五花八門,什么我認為女人能頂半邊天。女人應該靠自己。。。。。還有50題的智力測試。(就是那種幾個圖形,要你選擇最相近的一個之類的)。我是亂來一氣,我一直以來都不知道這個到底是怎么回事,都是直覺。同步進行的是hr面試,一個一個的叫出去,大概每個40分鐘左右。
5,終于輪到我面試了。進門前,我沒有敲門,直接開門進去了,說了一聲下午好,面試我的是hr和一個部門的manager,在整個面試期間我覺得最好的就是他們很尊重你,他們對你的情況特別清楚,好像就是和老朋友聊天一樣。其中重點就是問了我的項目經歷,因為我有專利,他們特別問了我對自己專利所有權的看法,問我為什么基本上由我完成的項目,老板做第一專利人?
我說其實這個構思是老板的,雖然具體實施由我個人完成,但是指導工作和申請都是老板完成的。而且由其他的師兄弟也能夠完成,具體會找我來做是因為當時我自己提早學習了工具,所以老板覺得我來搞比較合適。他們開玩笑說是不是你比較聰明?我說:其實能夠讀到這個程度大家應該都差不多,我覺得自己屬于比較勤奮。他們好像很滿意,問了我對薪水的要求。我知道他們是準備要我了。
我問他們根據這幾輪的面試他們覺得我應該拿怎么樣一個薪水比較正常?他們說基本上他們會尊重個人的意愿,當然是在不會太離譜的條件下。我當時開的不高,他們給的也屬于我開的范圍里面。從這點可以看出,如果你個人比較牛,那么你不妨開出自己比較中意的工資。如果他們能夠給,他們基本上不會太拒絕。現在想來,當時真的開的虧了。
面試完以后,他們告訴我2個星期之內會給你答復。后來想想這個面試很重要,基本上要人也是這個環節,其他環節都是參考。問的東西特別的細,最好不要騙人,如果你是撒謊的話,hr會一步一步的問出來的。還會問一些你和他人相處的事情,不會直接問,他會一點一點的追問,在回答每個問題之前不要太緊張開口,想想在說,說話不要太快,直視他們的眼睛有助于消除緊張并且給人一種自信的感覺。
大概6天以后,他們給了我答復,希望我能夠加入他們公司。。。。
算來從第一次面試到給offer經歷了大概1個月的時間。自己的求職也算是落下了幃幕,雖然還有一家公司開的待遇比nokia高,但是我希望感受一下nokia的氛圍,所以還是決定把自己賣了。感謝gg在我求職期間給我的幫助和鼓勵。
在整個求職期間,我可能本身不是特別著急,所以心態很好,大概會有一定的幫助吧。還有在求職的時候,女生化一點淡妝真的很必要,這樣給人比較職業的感覺,雖然不一定要穿職業裝,但是一定要穿得得體大方。
最后祝福大家都能夠找到理想中的工作,也希望我的求職經歷給大家一點幫助。
本文來自面經網-求職就業好幫手,原文地址:http://www.51mianjing.cn
預處理器(Preprocessor)0 n# S1 W+ C8 m. b $ ~6 M$ \& T2 K* U& Z! |" I o 1 . 用預處理指令#define 聲明一個常數,用以表明1年中有多少秒(忽略閏年問題) 2 \& |+ t, D; d3 \, H #define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL0 y" |2 O4 C1 i0 P: `! I0 f 我在這想看到幾件事情:* J6 ?8 U6 l! A8 N 1) #define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)) m4 M1 _ [( t6 w 2)懂得預處理器將為你計算常數表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。 4 N7 R& k+ g1 u" t 3) 意識到這個表達式將使一個16位機的整型數溢出-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。 : @% a- C& `7 `) e& d5 b) O9 J 4) 如果你在你的表達式中用到UL(表示無符號長整型),那么你有了一個好的起點。記住,第一印象很重要。" b' k% ^7 |- Q% l1 L! k/ t$ G + I2 ^. l! A1 X+ F 2 . 寫一個"標準"宏MIN ,這個宏輸入兩個參數并返回較小的一個。: M% ~% I- @5 D' O2 ~/ \7 I #define MIN(A,B) ((A) <= (B) ? (A) : (B)) / ?" [) s/ _, R! q$ E, b8 i9 p 這個測試是為下面的目的而設的: 7 N% M5 O6 D' G k8 h5 i& P/ {+ U 1) 標識#define在宏中應用的基本知識。這是很重要的。因為在 嵌入(inline)操作符 變為標準C的一部分之前,宏是方便產生嵌入代碼的唯一方法,對于嵌入式系統來說,為了能達到要求的性能,嵌入代碼經常是必須的方法。 * E X9 T! O) _/ f' { 2)三重條件操作符的知識。這個操作符存在C語言中的原因是它使得編譯器能產生比if-then-else更優化的代碼,了解這個用法是很重要的。 2 k# n w. p0 _+ G: C 3) 懂得在宏中小心地把參數用括號括起來$ [8 c4 M+ E& x2 q* K2 r9 @ 4) 我也用這個問題開始討論宏的副作用,例如:當你寫下面的代碼時會發生什么事? ' a( N* C! B* K least = MIN(*p++, b); ! a8 Q5 g+ e9 O* L' {! l6 i # `1 c# ^* Z7 Y6 u# z 3. 預處理器標識#error的目的是什么?! m/ @2 _, y8 u/ t- o 如果你不知道答案,請看參考文獻1。這問題對區分一個正常的伙計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書呆子,那么應試者最好希望自己不要知道答案。4 C4 }5 v- ~7 o. i! e 4 b6 D6 d7 @% z z3 Y V0 o1 W9 D! `- B 死循環(Infinite loops) 7 ?7 k2 s1 {$ }0 j! _. B ' N8 j9 M: v) t' ?1 p 4. 嵌入式系統中經常要用到無限循環,你怎么樣用C編寫死循環呢? # h# \1 M0 u( | @" _ 這個問題用幾個解決方案。我首選的方案是: + K1 w* ]3 [% c / s4 f+ \% ^. H8 o4 @7 I! q while(1)5 |- V$ D0 \) {% c+ x( C: R {$ S& G( }8 |' Q6 D. L% B: m3 K . v/ A, B% r4 ?5 w8 y7 j4 H2 Q } & x" d; o+ ]+ C6 l; z1 I 6 X" A- Q, Z" U, J, e0 F0 E+ J 一些程序員更喜歡如下方案: 4 d; p9 [1 w. u) v5 U' H3 g / Y. M& [6 ?' Z- H6 U8 a& A* ~ for(;;)3 Q, h( y' z2 I+ `# X& n, Q {! f& [; F! b: ^( ~# A4 { 5 J9 i" H0 s( q K }" k$ n3 S- [! ?7 i1 E5 @/ x6 h 0 i" R, S, m9 t: T 這個實現方式讓我為難,因為這個語法沒有確切表達到底怎么回事。如果一個應試者給出這個作為方案,我將用這個作為一個機會去探究他們這樣做的基本原理。如果他們的基本答案是:"我被教著這樣做,但從沒有想到過為什么。"這會給我留下一個壞印象。 % U. y5 J6 Y5 N* T4 q 5 F/ Q& W" b; K" n: j) m' x 第三個方案是用 goto 1 N. g) K( P" P/ ] Loop: ' N! F0 q+ ~6 h' }) g2 m% Q+ A ..., Z3 T5 ~0 A5 W0 F" _ goto Loop; " Q' K4 A1 o1 L2 J/ P/ k8 Y 應試者如給出上面的方案,這說明或者他是一個匯編語言程序員(這也許是好事)或者他是一個想進入新領域的BASIC/FORTRAN程序員。! j$ y$ |+ c2 |# A1 D; Q! o : p* z7 ^; w; H " Q; O; a+ ~7 P# i* n* d 數據聲明(Data declarations) ( E- V# z, ?* o5 \ ( \+ V: N0 ]5 f2 t4 C6 B 5. 用變量a給出下面的定義 % v h+ a9 j4 L H9 g a) 一個整型數(An integer) K5 A# B& x0 o9 h+ M) J- V b)一個指向整型數的指針( A pointer to an integer) # u, d6 X6 Z1 P) \" E( d: l c)一個指向指針的的指針,它指向的指針是指向一個整型數( A pointer to a pointer to an intege)r : X" L" _' Q: w/ w n4 f9 D d)一個有10個整型數的數組( An array of 10 integers) 9 C6 z+ X9 _7 H1 L1 G e) 一個有10個指針的數組,該指針是指向一個整型數的。(An array of 10 pointers to integers) ; y- j) S- q4 C4 ^6 s6 t% o/ t2 u5 n; N0 x f) 一個指向有10個整型數數組的指針( A pointer to an array of 10 integers) + c- L& d8 I1 E& ^6 J$ g% ] g) 一個指向函數的指針,該函數有一個整型參數并返回一個整型數(A pointer to a function that takes an integer as an argument and returns an integer) v5 t. D. [6 ]4 Y2 n h) 一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數并返回一個整型數( An array of ten pointers to functions that take an integer argument and return an integer ). s, k( g& l9 g; _0 M. f : @4 t6 M8 o$ J3 t 答案是: 5 N* N) C% t2 x7 K% x* e2 N; n5 ~ a) int a; // An integer # z: B& D4 [7 Y! ]6 Q b) int *a; // A pointer to an integer 4 x' Z- A0 z8 U c) int **a; // A pointer to a pointer to an integer 6 q, A9 R2 \4 j) x d) int a[10]; // An array of 10 integers 5 q5 m4 ?8 E: Y% i0 E; V e) int *a[10]; // An array of 10 pointers to integers 0 G: \% S1 ~1 q( S& W; n f) int (*a)[10]; // A pointer to an array of 10 integers 1 z" i! t) A5 I% o/ y g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer 3 R8 }4 |3 A- F" x% r) D% q3 a h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer 8 b. {' F5 p% [' l ; H$ H6 f( `5 ^& X 人們經常聲稱這里有幾個問題是那種要翻一下書才能回答的問題,我同意這種說法。當我寫這篇文章時,為了確定語法的正確性,我的確查了一下書。但是當我被面試的時候,我期望被問到這個問題(或者相近的問題)。因為在被面試的這段時間里,我確定我知道這個問題的答案。應試者如果不知道所有的答案(或至少大部分答案),那么也就沒有為這次面試做準備,如果該面試者沒有為這次面試做準備,那么他又能為什么出準備呢? ) Z2 ?& ]3 X. A6 b7 L' p( i3 v% X % t/ S/ s! E7 ~8 I) ?9 U Static 2 s9 \ b3 h. R* b, h 9 K3 i$ L# Z% m 6. 關鍵字static的作用是什么?% v( y) E: E- B$ z, s 這個簡單的問題很少有人能回答完全。在C語言中,關鍵字static有三個明顯的作用:5 m: B! t+ Z; n" b. W. b9 w5 m2 r# R. M 1)在函數體,一個被聲明為靜態的變量在這一函數被調用過程中維持其值不變。 % U9 O- |% ^4 T- p0 o: u6 h; M$ W 2) 在模塊內(但在函數體外),一個被聲明為靜態的變量可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變量。 1 }* @% k* h8 u( `/ d& p 3) 在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。 5 E8 W. a5 ~& J) W" r/ O . Q. R; N, U$ i5 W. r 大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個應試者的嚴重的缺點,因為他顯然不懂得本地化數據和代碼范圍的好處和重要性。( y; w5 p) \& {; x9 H/ O / p- u' L1 s( @! O) u# g5 w* T ; @( s; R/ k7 Y6 x/ |( C1 ?! ` Const % y9 O* t# P8 y H4 v ; m% |0 Z7 ^$ z! x 7.關鍵字const有什么含意?" d3 f* M, k% z& n$ c 我只要一聽到被面試者說:"const意味著常數",我就知道我正在和一個業余者打交道。去年Dan Saks已經在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味著"只讀"就可以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)5 H5 [: G" L0 B* W 如果應試者能正確回答這個問題,我將問他一個附加的問題:4 G' S" F" b) K# s* U 下面的聲明都是什么意思?, O, O$ w( d" V 3 Z2 U* n* L7 Y$ c( ]# B const int a;8 |6 `& m6 U. N* G7 p5 P; S int const a; ' c: B: P ]! N1 ]6 Z const int *a; % v+ m; y) e& o int * const a; % z- O: Y g: R8 `( y {: y5 x int const * a const;, W+ i& r. Z9 {) l ; O+ l% H9 ] ]& S0 {" Q* ^ /******/3 J& @% |, Q* W1 C( u 前兩個的作用是一樣,a是一個常整型數。第三個意味著a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最后一個意味著a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。如果應試者能正確回答這些問題,那么他就給我留下了一個好印象。順帶提一句,也許你可能會問,即使不用關鍵字 const,也還是能很容易寫出功能正確的程序,那么我為什么還要如此看重關鍵字const呢?我也如下的幾下理由:. O. E& ^- b5 ?+ K( S 1) 關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多余的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。), m% \ J X; P! A; W: x 2) 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。. v& H1 I' T: V) c9 W% f. i1 S 3) 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。2 l0 Y* t9 F& W7 Y( ^7 e. p( L6 c 8 ^: d# D$ h5 i) c; q ; D% o$ b/ t5 D Volatile 5 X# }4 M" s- p l2 [ . S% ^/ c* w; U4 I" x/ ], C6 A 8. 關鍵字volatile有什么含意?并給出三個不同的例子。 8 [/ ~, Z* p" w# f5 [! h1 t 一個定義為volatile的變量是說這變量可能會被意想不到地改變,這樣,編譯器就不會去假設這個變量的值了。精確地說就是,優化器在用到這個變量時必須每次都小心地重新讀取這個變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個例子:: h9 R) A( |* k 1) 并行設備的硬件寄存器(如:狀態寄存器)' G+ m$ p! Y5 D6 l v' A% C 2) 一個中斷服務子程序中會訪問到的非自動變量(Non-automatic variables)7 [5 A6 E& G U1 ]9 P" z# } 3) 多線程應用中被幾個任務共享的變量% V$ ?& X: v8 c) T" M% ? " o) R% y+ i3 h/ l5 a) u2 L 回答不出這個問題的人是不會被雇傭的。我認為這是區分C程序員和嵌入式系統程序員的最基本的問題。搞嵌入式的家伙們經常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內容將會帶來災難。 - g+ D V1 E# z$ z4 b 假設被面試者正確地回答了這是問題(嗯,懷疑是否會是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。! K! H; b' ?, x 1)一個參數既可以是const還可以是volatile嗎?解釋為什么。 & {' o0 r! D& B/ q: T* m1 q 2); 一個指針可以是volatile 嗎?解釋為什么。 3 a$ j4 M! \4 E% Q. U& F/ C: | 3); 下面的函數有什么錯誤:* k; n; ?, O7 U" C+ V1 r ( V, Y' Y% e1 D8 R) T5 w1 b* W int square(volatile int *ptr) 2 R9 N: B- O& s! p { # o& o- s- _) C* ]8 ` return *ptr * *ptr; % Q5 H2 q2 }: h9 C- @( _% | }$ L6 P- o( J, n: Q 1 r5 f& R" {& _$ X# |0 U 下面是答案: + e# T" h3 h0 d' L 1)是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。 8 b& [ N$ ^1 _5 l' ], P 2); 是的。盡管這并不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。& {% J3 F3 N, M0 }# \3 h 3) 這段代碼有點變態。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由于*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼: |- k3 U! M2 f( ?6 v' _ 8 B- n, K+ x* V s2 o int square(volatile int *ptr) # b8 B& F( e; B0 Y, _3 f {8 U. g1 p" H5 Q' O# Z- M- @, u int a,b; ; O2 Q; C% S& Z8 }. Q' @ a = *ptr;, f2 V5 ^1 X% u1 Q0 I b = *ptr;" D4 B4 @% W: N, x return a * b;; b( n0 O* M" m }' x* U. _' U1 i4 q$ \# D " l: H9 f$ P1 l6 W! Z$ P. b9 M- b 由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下: & y) ^2 ], [" E9 A7 i# N$ F* ? ) ^, t' Q+ Y. u2 T8 g long square(volatile int *ptr) / I N5 m$ l1 X {9 Y) I/ i. S1 s( {3 u6 c8 R4 F int a; - L/ w( `% i" z; [+ B0 } a = *ptr;" Y9 B4 S6 ?: W7 T1 ] return a * a; 7 w: x3 j: o; T4 V! m }+ s* Z/ v/ H/ m% G 6 g+ X7 F2 q' P3 Q* `, S 位操作(Bit manipulation) , E$ w' G- @: {" y ( n5 j, v0 N+ d% E2 h ^+ u+ V 9. 嵌入式系統總是要用戶對變量或寄存器進行位操作。給定一個整型變量a,寫兩段代碼,第一個設置a的bit 3,第二個清除a 的bit 3。在以上兩個操作中,要保持其它位不變。% j5 n+ |' `# d 對這個問題有三種基本的反應 ( ~5 g( @9 ~! i9 q. T. L, { 1)不知道如何下手。該被面者從沒做過任何嵌入式系統的工作。 * C. Z4 ]' ^+ @. @. R1 S# y8 g 2) 用bit fields。Bit fields是被扔到C語言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時也保證了的你的代碼是不可重用的。我最近不幸看到 Infineon為其較復雜的通信芯片寫的驅動程序,它用到了bit fields因此完全對我無用,因為我的編譯器用其它的方式來實現bit fields的。從道德講:永遠不要讓一個非嵌入式的家伙粘實際硬件的邊。 % g+ w- L* s, X( C V 3) 用 #defines 和 bit masks 操作。這是一個有極高可移植性的方法,是應該被用到的方法。最佳的解決方案如下:) Q" a2 Q" S) T4 ? 1 F" I; a1 k8 _8 W8 H #define BIT3 (0x1 << 3)6 [2 L5 C! D" o5 }3 y/ ? static int a; + b& Q! b+ ]2 b Y& _1 B m8 j/ i r+ a) O void set_bit3(void) 3 O) C, i; z# g: p3 O: W {0 c/ p8 J" Z7 G$ b a |= BIT3; ' L6 f# V. b5 A5 u7 T }$ r( S) t: s$ F4 \- X+ m o1 v void clear_bit3(void) % b' S5 Y3 |' r7 a {/ N! ]9 c0 r& V9 X1 E- V( z a &= ~BIT3;# q$ I n, J9 l8 ~& F" p) G }4 D1 L2 V" n+ K' ]2 [8 ~& C / e2 M- e* W. s 一些人喜歡為設置和清除值而定義一個掩碼同時定義一些說明常數,這也是可以接受的。我希望看到幾個要點:說明常數、|=和&=~操作。6 x, j7 r i8 b& [0 q' n( K % i+ D, I4 g# S& V6 ~6 p6 [8 @ Z 4 s1 A+ G$ |) A" f) v% v 訪問固定的內存位置(Accessing fixed memory locations) , K) U' H4 T8 I* i0 ~ % @: _- ^, N# r4 R" z5 ^ 10. 嵌入式系統經常具有要求程序員去訪問某特定的內存位置的特點。在某工程中,要求設置一絕對地址為0x67a9的整型變量的值為0xaa66。編譯器是一個純粹的ANSI編譯器。寫代碼去完成這一任務。 z) n9 w3 b% N! Q( V 這一問題測試你是否知道為了訪問一絕對地址把一個整型數強制轉換(typecast)為一指針是合法的。這一問題的實現方式隨著個人風格不同而不同。典型的類似代碼如下:7 g3 {/ f1 N9 A int *ptr; / f6 {& ~" _) L$ g* {1 ] ptr = (int *)0x67a9; 1 f3 m5 S4 g$ U, P *ptr = 0xaa55;8 W0 U4 m( F, ` - C2 I' G5 T; ?9 D3 m A more obscure approach is: r# a4 R6 L) r. A& [ 一個較晦澀的方法是: ) K& s! X9 h; g. |& p7 q1 U & j0 D( k4 s$ G" w3 D1 E1 L$ D( v& Z *(int * const)(0x67a9) = 0xaa55;% j8 R8 O3 m- [; o' g, x 2 _1 D. p. d; K; o# Y 即使你的品味更接近第二種方案,但我建議你在面試時使用第一種方案。 7 e9 G1 k9 k0 n. E5 c2 u % H7 U/ v& r& C" H/ ^1 P. J 中斷(Interrupts) ( u# N( o( t+ m7 f# ^* N( V * q: K3 ]. B N 11. 中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展—讓標準C支持中斷。具代表事實是,產生了一個新的關鍵字 __interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服務子程序(ISR),請評論一下這段代碼的。 6 R- v. @1 s* l3 G 1 W) N: T* Q' A. c: { __interrupt double compute_area (double radius) q: f' }% K& ? {& A! B1 d1 L( N6 D double area = PI * radius * radius; % x/ Q5 N+ E4 c printf("\nArea = %f", area);( q/ A4 L* K# u6 o6 ] return area;" p! N( R& q/ `8 o1 a$ t. x$ I }: J6 `# p/ z$ V. R/ E( y : [3 o- o3 q% L( { 這個函數有太多的錯誤了,以至讓人不知從何說起了: f* m$ a+ s! o7 P4 [ 1)ISR 不能返回一個值。如果你不懂這個,那么你不會被雇用的。5 E) k# |% B+ U" \7 h0 b 2) ISR 不能傳遞參數。如果你沒有看到這一點,你被雇用的機會等同第一項。 + q; u9 H9 K* w$ [' f 3) 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明智的。 ( F. \6 s+ ]2 D 4) 與第三點一脈相承,printf()經常有重入和性能上的問題。如果你丟掉了第三和第四點,我不會太為難你的。不用說,如果你能得到后兩點,那么你的被雇用前景越來越光明了。 * g' [) M. I; i3 G6 a" i+ n) C ?' [! Z. D$ c0 x ; I! G6 B* M7 k* m' Q5 x. x 代碼例子(Code examples) % k- A: ^) H& Y; S# a; R, K . \+ q5 L& c C" Y& L 12 . 下面的代碼輸出是什么,為什么? : v5 M4 d1 U8 M! P& s: Q / b2 {; I+ F1 i7 o* n A void foo(void) 0 m! @+ X) y0 F7 G: y8 N5 Q% N8 X {7 K/ H, ]+ m7 C" A unsigned int a = 6; - z* U" ?6 w- Z/ \ int b = -20; 6 v" \/ Z3 m9 f9 G% K% {6 P9 d (a+b > 6) ? puts("> 6") : puts("<= 6"); ' E' }, P& a, }! w i2 s: f1 C } 0 T3 n$ }$ j" `& Z1 f 這個問題測試你是否懂得C語言中的整數自動轉換原則,我發現有些開發者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是 ">6"。原因是當表達式中存在有符號類型和無符號類型時所有的操作數都自動轉換為無符號類型。因此-20變成了一個非常大的正整數,所以該表達式計算出的結果大于6。這一點對于應當頻繁用到無符號數據類型的嵌入式系統來說是豐常重要的。如果你答錯了這個問題,你也就到了得不到這份工作的邊緣。 3 U, ?# Y: V! e% B' ^ ; y/ H2 i0 z0 s8 ^7 z 13. 評價下面的代碼片斷: 9 b, I: k5 b2 R8 B3 r5 ? m# s9 H , }& d+ t# q3 ]. ?1 Y* j! F unsigned int zero = 0; . Z- q5 j2 A: }; F3 x, y% J) G; `6 k+ o unsigned int compzero = 0xFFFF; 6 x {6 b5 N! E9 E8 k4 b e /*1's complement of zero */7 o7 _0 V t F3 ^. z 5 A4 z; U6 k6 d, n& W: l' A# I 對于一個int型不是16位的處理器為說,上面的代碼是不正確的。應編寫如下:& |5 P: S/ f& _8 w. v 1 X7 c8 F( I H9 C C* p unsigned int compzero = ~0;) T% _ m" | x2 ?5 _9 D. F: u, B3 X , u( F$ u2 o* g' ?" U7 m 這一問題真正能揭露出應試者是否懂得處理器字長的重要性。在我的經驗里,好的嵌入式程序員非常準確地明白硬件的細節和它的局限,然而PC機程序往往把硬件作為一個無法避免的煩惱。; \. G' E; y7 a3 S( V# ?( [ 到了這個階段,應試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應試者不是很好,那么這個測試就在這里結束了。但如果顯然應試者做得不錯,那么我就扔出下面的追加問題,這些問題是比較難的,我想僅僅非常優秀的應試者能做得不錯。提出這些問題,我希望更多看到應試者應付問題的方法,而不是答案。不管如何,你就當是這個娛樂吧...( R. U0 x) H- ?/ K- H; N( { : a1 i) N0 _8 @' l) u" e $ m" d' z$ o! G& w3 A. x- D& r 動態內存分配(Dynamic memory allocation) $ N3 r( C5 m! R# D) J+ N1 J" U ) U1 c$ W6 }; W$ ] 14. 盡管不像非嵌入式計算機那么常見,嵌入式系統還是有從堆(heap)中動態分配內存的過程的。那么嵌入式系統中,動態分配內存可能發生的問題是什么?1 S% u) _9 L4 l( h4 v4 m 這里,我期望應試者能提到內存碎片,碎片收集的問題,變量的持行時間等等。這個主題已經在ESP雜志中被廣泛地討論過了(主要是 P.J. Plauger, 他的解釋遠遠超過我這里能提到的任何解釋),所有回過頭看一下這些雜志吧!讓應試者進入一種虛假的安全感覺后,我拿出這么一個小節目:! P! f l' ^4 k 下面的代碼片段的輸出是什么,為什么?$ O5 @) Z! q. y* M9 I # T; e" {. T/ n* x char *ptr; ' j* O% c4 z/ B+ T7 ]7 B if ((ptr = (char *)malloc(0)) == NULL) ( T3 T, h. c+ b# H puts("Got a null pointer"); # P' ?9 ^( e9 Y6 h$ i$ u else 5 R8 t- p! P) q2 Y m" w puts("Got a valid pointer"); + l0 t" F: s1 O 6 B9 G! o& g% q, u0 z2 b1 Z 這是一個有趣的問題。最近在我的一個同事不經意把0值傳給了函數malloc,得到了一個合法的指針之后,我才想到這個問題。這就是上面的代碼,該代碼的輸出是"Got a valid pointer"。我用這個來開始討論這樣的一問題,看看被面試者是否想到庫例程這樣做是正確。得到正確的答案固然重要,但解決問題的方法和你做決定的基本原理更重要些。: u0 l9 e5 B) B& o8 E 5 p7 s9 A% x$ ?( b8 J Typedef ; w3 `, I) i( A+ j ; `+ T) [) p; l* r" u, K! Z" S 15 Typedef 在C語言中頻繁用以聲明一個已經存在的數據類型的同義字。也可以用預處理器做類似的事。例如,思考一下下面的例子: ) p8 ^5 ?' e* N8 @6 W! H" s 2 l5 q+ p6 i4 k# N% m! N #define dPS struct s *% O: x9 \% d) U7 a1 T0 D/ X typedef struct s * tPS; 8 j8 T* u" A6 _3 r # @+ A3 l1 M4 O' |( y9 r% ? Z 以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個指向結構s指針。哪種方法更好呢?(如果有的話)為什么? " T4 ~* V3 z* A( k% c$ o 這是一個非常微妙的問題,任何人答對這個問題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子: 0 k2 \ A+ e) @- z + n7 U: a9 ^- y dPS p1,p2;3 B4 m$ F- M' d+ w7 [. } tPS p3,p4; ! G) {- h" M- B5 O* Q. ?; U 8 G% d$ A! d. {+ l+ l 第一個擴展為" o) W7 P) O! d8 u( x4 p 5 ?. S" X+ D$ v$ J struct s * p1, p2;5 ?" z, y5 h: s7 ]! \# y . 0 H% T$ m% J( q {& g( x 上面的代碼定義p1為一個指向結構的指,p2為一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。 0 |' J8 @' f) ]# X* g$ w" ? 2 A- J" q% w! g, f0 I9 S . `! @7 r* z5 J8 X ' o( f$ E. s1 o2 r; z+ S 晦澀的語法 . m% @, }* z: _ 0 c# d, d. B ?3 S( T6 B 16 . C語言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什么? 5 ~& T6 |, H( e* j + \" x: g x8 L! _& s& B int a = 5, b = 7, c;+ \8 ]9 e- p, J& n, L; b c = a+++b;/ d6 q7 `' J4 j2 s! o7 | : b+ \" U* Z+ h5 A2 i+ a 這個問題將做為這個測驗的一個愉快的結尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理盡可能所有合法的用法。因此,上面的代碼被處理成:, |8 _0 C; \* m( o1 Y4 e" I - l: I# P, O/ e3 M+ h0 `- v c = a++ + b;7 G8 \& W/ a& K6 s 4 f2 _$ N( Q/ H x& i" N# `! D) g 因此, 這段代碼持行后a = 6, b = 7, c = 12。 ' w+ E* S; O3 q, `3 I' K. ]% @ 如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個當作問題。我發現這個問題的最大好處是這是一個關于代碼編寫風格,代碼的可讀性,代碼的可修改性的好的話題。, M( X# L9 z# z3 x' R9 U ( f- ?! ?% ~) h: n& m3 t5 F ! k z) e3 u- K) H0 h5 X- A8 s- _: M n* w& W; f( e% @ ! w! L {. l: s5 I- q / s5 q& W- o6 Q1、將一個字符串逆序 3 L1 f" I G; V8 D) o+ n2、將一個鏈表逆序 / k. J$ B! y% E! z9 U 3、計算一個字節里(byte)里面有多少bit被置1 ' o9 c' p+ O7 A" e! r a9 t 4、搜索給定的字節(byte) ! {, j# F- E" {5、在一個字符串中找到可能的最長的子字符串 1 b2 R* `& {7 I6、字符串轉換為整數 : a& k+ V2 F1 }7 t5 v* r 7、整數轉換為字符串 |
1、 編寫函數從一個包含由逗號分隔的100個16進制數的字符串中提取這100個16進制數,按從大到小的順序輸出其中的偶數。$ m; f1 y# }+ S9 M 解:此題按步驟解即可:先解析100個整數;再對其中的偶數排序;最后輸出。 8 s7 O7 V8 v& E2 A( t " g- Y! o, m' L#incluede<iostream> 1 X( s3 k2 q' n3 Q$ ~5 V: Rvoid coma(char *s,int b[],int bl) 9 k0 b4 j1 O( D2 C: Z0 P{8 j9 j O. @/ o- Y2 e5 K \' S% M int i,j=0,k;; i$ v u0 G0 R6 i9 _( L/ w / Y' x$ l8 G1 l2 w4 I! G. o //將字符串s按分隔符’,’解析成100個整數,存放在數組b中 $ [" ], q4 |9 e' V for(i=0;i<bl;i++) ' u/ j1 o& y$ V) A" u# t1 f { 8 r# ?; ?6 v9 Z2 g0 A* d while(s[j]!=','&&j<strlen(s)) + c* J: t, l2 l2 [4 D { / Q; T6 Q( L% o4 Y5 h1 J" r if(s[j]>='0'&&s[j]<='9')# a8 d) o! I" M* } k=s[j]-'0';5 |5 Z& \+ q4 P: G4 c else if(s[j]>='a'&&s[j]<='f') 0 q( p9 D6 K) i k=s[j]-'a'+10;# S0 ~7 |* Q$ Q/ C" s b=b*16+k; 7 T7 V P9 ]0 \+ v j++;* v; o" w) S W) B- w4 X4 d }3 S/ V7 v" t; D6 D j++; 0 h1 s* c# B3 `0 V }, @% |: T1 F* R" B @" K & a+ k+ U' M0 y% T int max; % F* |; X' H3 D% \" f' ]5 w int blen=bl; 1 w5 o D4 N, X; W; q. k; \ int cur,t,even=0;. u% l7 z# e! h2 a/ M5 c& k1 ^ , p: e2 Y+ l/ E* X( T/ p //對b數組的偶數按從大到小排列,交換到數組的前端。 ; m5 E1 p3 L: O3 p; ^7 `+ A9 D2 w for(i=0;i<blen;i++): u" l/ v; a+ s/ L, l$ u3 R- b" v { 2 Y+ d# [ M- ?$ d, b max=0;% A, ~3 B! I0 ^ cur=-1;2 Q! H& O7 R; Z. h: F+ q //j從i開始,因為i以前已是有序偶數,且已從大到小排列 4 ~( I' I& G& z0 A( T for(j=i;j<blen;j++) ! C9 |) V. R; [2 Q4 G9 y1 W( k { . x; \2 N9 u; {* X8 v+ \; Z if(b[j]>max&&b[j]%2==0)% I M% S2 ]: k/ Y { # T1 n$ K" t9 K% k9 A max=b[j];1 [( `' G- I3 E8 r9 I cur=j;2 k& P1 ?& A9 z$ J6 K) K }- P( T" n% w4 \9 \0 F3 f. r } 5 g$ ^+ K0 r! `0 e3 r; O+ u6 ?5 H: d0 G' o' q //找到剩余數組中的最大值,交換到數組前端7 j+ ]+ T, |' ? j. u7 Z if(cur!=-1)& Q( Q( w( Y3 j) }$ X {, X3 N& e8 S' W# k2 W# f t=b[cur]; ( T. y. d, Z1 A. G0 ~, I$ v b[cur]=b; 4 j' `) R( F/ A) I# f1 z+ B b=t;' d4 j# m& q" I1 Z even++;$ w/ r6 o; _, j } ! g7 D! Z* x+ C0 E6 N0 J" T+ ?6 T //剩余數組找不到偶數時,跳出循環' _7 \$ _2 n6 v else : V+ Y# }' C6 E- L$ g* }8 x( d3 w8 f9 w break;, h8 g" Y+ R5 O$ h } 5 k3 G; o' c$ B6 a5 M7 |* F! V+ N( Y) u //輸出前even個排序好的偶數3 q' F2 [3 g% u; Y5 f# [; s1 [ for(i=0;i<even;i++). P1 H7 \3 K+ r9 K7 d8 H# K4 R //十六進制格式輸出 & r5 Z; t7 L7 M9 j' A cout<<hex<<b<<" "; " n' a7 `* G3 Y: Z c+ s l. A //printf("%x ",b); n o$ [, X( A# L# {" e 6 w6 \& k2 G( {/ W7 p5 n cout<<endl;& o6 A8 u& {3 k3 W" |0 T# b return; [1 D- i7 _ ~" S1 g/ @} # V4 L3 T" m. ~- ^- ^* u2 y% Z! _" q1 _' h2 a& Z1 Y) X* @7 C //測試: C9 N1 |; Y; J' s7 o( m+ g; l$ C int main()' B3 R* k: ^, W; e {! k9 [/ m v: }. `/ f3 J2 A char *s="1,2,3,4,5,6,7,8,9,a,b,c,d,e,f,10,11,12,13,14,15,16,17,18,19,1a,1b,1c,1d,1e,1f,21,22,23,24,25,26,27,28,29,2a,2b,2c,2d,2e,2f,30,31,32,33,34,35,36,37,38,39,3a,3b,3c,3d,3e,3f,40,41,42,43,44,45,46,47,48,49,4a,4b,4c,4d,4e,4f,50,51,52,53,54,55,56,57,58,59,5a,5b,5c,5d,5e,5f,60,61,62,63,64,65";: G/ h0 _' U1 Z6 R0 c int sb[100]={0}; % L* d0 c; W6 w/ b coma(s,sb,100); % q. ~) o. R, Y& v1 i& A6 Q3 Ereturn 0; 0 c; u! @+ K. s6 b4 J1 j: ^}6 K9 k/ ?* d- H5 u: P- T9 c $ j* n6 Z0 r1 p! q- U) [ 測試輸出:+ P# b9 f9 Z' i' C; c! `2 e3 j d! v 64 62 60 5e 5c 5a 58 56 54 52 50 4e 4c 4a 48 46 44 42 40 3e 3c 3a 38 36 34 32 30 2e 2c 2a 28 26 24 22 20 1e 1c 1a 18 16 14 12 10 e c a 8 6 4 2 0 . }. _! S) s' b8 x7 G4 E% \0 K5 r6 `' a {0 Y 2、 編寫函數數N個BYTE的數據中有多少位是1。4 K, o9 T9 Q) D, v 解:此題按步驟解:先定位到某一個BYTE數據;再計算其中有多少個1。疊加得解。 3 \7 y- ^& h: ^( v) E5 s ' I3 {$ {; h- z$ x0 ]: b#incluede<iostream>8 H7 T+ m2 @$ E& c #define N 10 5 U) P% X9 M4 d' |! U- \//定義BYTE類型別名 : ^9 J; Y% X4 ^2 g#ifndef BYTE # @4 K% X$ E: o5 y/ A9 {typedef unsigned char BYTE; ; V4 k3 Z8 t1 w$ [% F0 \#endif 2 {9 t8 ?( w6 E! H, l! d( V4 X) {( n: I# ?+ t2 | s* r int comb(BYTE b[],int n)' f9 r0 ?1 ?9 ~& M' ?: u { " C$ @% l/ U' S) ~% c) r" } V- o& H int count=0;' g( j& [7 ]7 P$ h6 [" J- p int bi,bj; Q- I$ L" {) X, u5 l& {1 s* I BYTE cc=1,tt;4 ~0 q4 G) q0 s* _ y* n ; S: }& K1 J8 M: @$ J c//歷遍到第bi個BYTE數據 5 R5 V% t" N, @ K for(bi=0;bi<n;bi++)3 f3 z5 b7 U$ A2 n" {, y { c& x) _. X# A//計算該BYTE的8個bit中有多少個1 r5 [ ?! V; u0 ~) O7 y- f! b tt=b[bi]; ) g6 R$ r: n- i: `0 p for(bj=0;bj<8;bj++) 4 W8 O% k) r2 f& F, L { 1 V. ]- b: N1 i! D0 | //與1相與或模2結果是否是1?測試當前bit是否為1 % G' u5 ?* R7 C //if(tt%2==1)& d! L j3 _5 x% L if((tt&cc)==1) # Y3 w+ f' k2 T4 `% y3 _- v" f! J, K { 8 ^# D( P; {1 T- P* e count++; 0 I7 [' h1 e3 C, [: I' U$ J } ; Q9 R4 H4 k' f. q( e3 N. @ //右移一位或除以2,效果相同7 `" t! y, ] e! l' I5 c2 @ //tt=tt>>1; ; l, _' ^$ S9 U* Q tt=tt/2; ; x) ^6 M# k% s/ @6 x$ l* M } ' J& y% W$ u: l- Q5 s }, E* V2 z& b, @# k4 } return count; + \& R7 C/ u2 K} # g) i4 e- x0 D, d7 Y7 ?/ w( x( ^ l2 }8 Z% C9 A) t //測試! ~' G" a# b0 |! v int main() & N+ T& m8 w: l/ P( y0 I: l{ 9 d" E) d8 J" r2 j6 o/ b& QBYTE b[10]={3,3,3,11,1,1,1,1,1,1}; $ r. p, v+ r ~3 n cout<<comb(b,N)<<endl; 7 ` N( P- {5 X/ r return 0;9 N7 M. _0 j8 y4 Y. I. V } + u4 j @* J0 O3 Z; X, F 6 R+ Z; H0 W" X測試輸出:3 Q( s: a Q3 O9 n7 R4 \# R j! N 15 5 A' V0 n6 L6 j0 }6 z4 t 2 | }7 |* ^+ s. A+ |$ [ _3、 編寫函數比較兩個字符串。 5 Q" g$ A( p# `8 c4 u. {解:此題簡單,可能只要注意一下下標越界問題。 9 @1 `# h' ^( [0 k* u: }5 n+ S9 h; a. E# q #incluede<iostream>0 a$ s2 p' Y% j3 ]7 g& [5 }* n int mstrcmp(char *st1,char *st2)& \5 T) U% p7 q4 b { l6 l7 M# l! F8 s8 o4 X$ v$ j /*注意到當st1,st2任一為空時,*st1==*st2測試為假;當st1,st2同時為空時,*st1==*st2語句為假,故不會越界。*/ 2 w& _9 f u7 g, I) S B) t while(*st1==*st2)9 j* j* A5 ^2 @- i {( ~2 w! I7 X1 m8 V st1++;( i, ~# B* U6 } st2++; 5 X4 _, O9 H. `7 I( K& o2 X } 8 V# X1 c- v# r. N2 E# q if(*st1>*st2), Y/ y2 R* ]4 _5 G- M# w return 1; & S5 n% @% @7 k2 t9 w% a' \ else if(*st1<*st2)% q* p" ^" _3 l! K& R8 f return -1;& a, W# x" d' h else 9 W$ U) Q- I, f1 D' ^ return 0;6 G& x' j f8 S9 f: Y9 q1 V1 k } ( J+ t0 L- j0 u7 B! ~, i$ K 1 W7 } Q9 H3 d//測試; w! H ~' u6 D% g, h int main() 9 x- Z4 K+ i9 O ?9 F/ W7 `{ - q, G3 e# s) [ char* x1="def2";: S# n$ t! j# A char* x2="def223"; " [$ ]/ C5 O' W: V1 V/ ] //c標準庫自帶字符串比較函數 0 Z5 i$ r' y9 r' Y cout<<strcmp(x1,x2)<<endl;2 j! U6 \( W' j5 ]2 B //自己寫的' ?* X, ~! H9 @% G% g cout<<mstrcmp(x1,x2)<<endl;8 E$ s+ q# g5 x5 T( b } 0 F$ m, R7 _& g% V; B v1 i4 C) Y% Q2 r. h6 j 測試輸出:$ b) F- i9 P& ]: o3 R -1 % u9 C7 ?) D5 E-1 1 c: f: E) ]7 g8 R9 W3 D* D3 v% B# f- B 4、 計算一個結構占的字節數,及在緊湊模式下占的字節數。. r$ H0 G1 R R& U4 J/ B" k8 x 解:char占1個字節;int占4個;short占2個;long占4個??紤]到位對齊:char 占1-4字節;int占4-8字節;short占8-12字節;long占12-16字節。緊湊下不知道如何編寫代碼,但應該不用位對齊,故估計輸出應為:11,00000007。) ] O2 a3 c* W; h( q+ ~ 這里要提醒大家的是:位對齊與類型的排列順序有關。若類型排列為:int char short long,則int 占1-4字節;char占4-6字節;short占6-8字節;long占8-12字節;此題輸出應為:12,00000008。 , n, A4 V4 u1 f1 x 1 X1 c8 q$ k( k$ X c8 _#incluede<iostream> 8 t/ @2 r o8 x: ^0 R0 D: l" ktypedef struct _st4 Q8 M6 e/ j0 ~: p( a9 N8 Z { ( y( y5 e4 j- y/ M8 _! B9 y) s char a; 6 m1 o+ c* u+ q9 g( Y" K7 s0 G int b;9 b% L& u2 {* u" `. R2 ~) ^ short c;: f, x- h$ C/ } n( P9 }/ B" L' b long d;6 l+ j" F: d" ~7 P" _ }0 u1 N/ N! A# [" O; k st; 1 r/ b7 I8 o9 d9 j8 I; K" S9 v b, r3 R$ d //測試: 6 j$ l" o" a, z& Oint main() A. D) ^* `) A- j" H7 R {6 q; s3 Q9 ]2 m2 P) }3 K: o- P cout<<sizeof(st)<<endl; 0 R5 ?+ P9 I; N7 u2 y5 ?, I cout<<&(((st*)0)->d)<<endl;* \4 _# K' j: W- e# h" _. y return 0; 9 J2 `; G/ {# Q} # x, @- ]0 D* J6 R* O4 t) | . E5 w3 x4 X' u1 s, {測試輸出:4 l. D. u; S! h, @) z, N \+ G 16 / P7 I9 {; a$ f; p8 K0000000C# M( _0 r0 x: T5 t3 L 注:如何定義緊湊模式?求緊湊模式下的代碼。7 s+ s! Q& S5 |) E) O$ a" ^) P & o+ B! ]) `5 o, S) U5、 多繼承。 ' A% \2 }. k P解:virtual繼承是防止a-b,c-d型繼承時維護超基類a的兩個版本。此題中virtual繼承不影響構造及析構函數的調用順序。此題另一個需要注意的是:new開辟類空間時需要調用構造函數;只當該類空間被delete釋放時,相應類實例才會被析構。) u; n% u3 l4 U; \( \ " h- e+ i+ {4 L e, g#incluede<iostream>& M1 v1 I9 i& B) k class a7 j; T. l- v3 |# `/ L3 h! [ { # ?, {, A: @$ }2 Spublic: ; ~& |8 i* B# V: j) U) ~6 R a(){cout<<"a"<<endl;}- e" Y: K; a# x9 ]# L ~a(){cout<<"~a"<<endl;} ! q6 w' \3 C7 y};- C8 B" `9 a& N q% d7 B* T 2 \# r$ F: _' \class b : virtual a 4 Z+ `! {$ K/ @% Z{ : R: C9 t" a( B1 I$ @public: ' m) W0 j. q* w( {$ |2 c b(){cout<<"b"<<endl;}$ v' D8 Z( z3 ^1 g+ V7 v# H- F+ X7 \ ~b(){cout<<"~b"<<endl;} 3 }) p( U+ T3 D! `}; 4 o2 O) {& ^' K& T2 J" l5 P& [4 Q) ^/ z9 {" ?! q' Y3 k class c 6 j4 p x6 |0 T1 o! W3 e { 6 v, t. D6 U& }9 z kpublic: 4 L. F; i1 d( T4 S& B/ Q) ^# C c(){cout<<"c"<<endl;}8 @6 w4 ~& Q! d y0 Y) W. q1 i ~c(){cout<<"~c"<<endl;}* Z) T$ d, g2 U7 M$ l }; 4 F4 ~3 j3 ~1 _+ e* n# i( ? & q: O+ s+ d2 N. @class d : public c A1 n8 ]3 X. K& T4 T {) r0 r; c n1 \2 k2 c public: 5 c/ I* [- ]- P d(){cout<<"d"<<endl;} b( i+ {# k1 o, m ~d(){cout<<"~d"<<endl;} 9 l& i8 W. P- Q: y# [" u6 B};' m7 U( D ]8 A5 }$ ] - p: O1 _ t/ x- p/ fclass e : public b, public d 6 O( o+ _6 W& m7 ?, [ r{ ; s; \ y# }* z+ d3 R$ e1 p1 n( fpublic: 0 D( H* t D" O$ _" V+ c, | e(){cout<<"e"<<endl;} / k3 S4 x( R% R/ O ~e(){cout<<"~e"<<endl;} 5 y; m# T8 N) e9 w};; \. C9 ^5 W( o, u1 r0 N * C; A1 o# x* i( X" [0 p//測試 & F0 o8 o9 _* Q+ M4 x- cint main() 0 n: N, Y+ C6 M$ V0 k{* X/ a- T7 K9 j ~" x7 J a e es;9 X1 W# u7 C% A/ J1 ?2 V n) @ p! m e *ep=new e;0 R8 \) _2 N/ h* J$ w( t //delete ep; / q2 Z+ m( B. [1 \7 M5 z8 s return 0;# v) x5 {, ?& s* i: T } , y; }+ J6 c6 U; \8 C4 _- ~8 ^$ B+ L: v& \+ d //測試輸出 6 X' u( B3 n) j6 c( e' Ca 9 A% p7 _: n1 J" `) G( M% {b6 V( u) Q7 z0 z9 ?# P6 `' s c7 e5 l* r; T$ W d * r+ m+ a) z, i! Ie8 Y5 G6 T7 z( A& Q- b a2 C. R) E/ A& @5 Q4 z! k b4 i7 u! z9 L5 j. b O c : }- c9 V% S2 ~9 zd5 p$ Y4 I" R% h+ |* G e , `' q9 l( A9 Y9 l$ N" m* _# S~e 5 x2 i% T6 R2 X% A" t5 W~d' L# S- N0 e0 |" E q4 f: e2 J ~c+ g3 d T5 R2 p8 T( M7 m4 m ~b+ }7 m5 F3 L& S- m- a ~a8 m0 y. U" z) x 4 p: L }* Y8 N 6、 編寫String類,實現加法和賦值運算符重載。 2 D& L; F5 h5 g解:此題名不見經傳,實現中需要注意:必須實現拷貝構造函數,在加法重載中返回一個類實例才能成功。' T3 L& B0 X5 U% @& r, M/ N+ F . Q/ J* L, L- R% G#incluede<iostream>1 Q- `; |2 G4 E4 O7 R% ^+ b c$ ] class String+ c2 s3 Q9 c- o( L8 b/ o+ D- V, { { * g* O' S. m1 s" @5 Xpublic:$ F( H" }$ f/ u' P //構造函數5 G- M; @ s- b& ~( Z; t2 d5 M: e" a String(char *s=0,int len=0):len(len) 3 n n) n; n) q8 ?, a; z, _" h {, \: \1 u1 ^' c& G1 g) d7 J this->s=new char[len]; 3 w- t+ I3 I9 x n. l1 n int i; 2 L# o( Q# Q; e+ N for(i=0;i<len;i++) " r" _) g4 C# Z3 p" A( b4 s this->s=s; 3 W+ a% L) c5 ~3 z }+ E; a/ x! D9 s! `9 I //析構函數 ! j2 }, Q6 |* g4 k ~String(){delete []s;len=0;}) ]) I) u' v3 w3 K2 y2 t$ P void prints();7 d ?- I) {9 ?" ]6 }- N' C String(const String &str); ; G& i/ v- v) q; j9 U2 Z$ E7 a: r String& operator=(const String &str); & \" Y. D. d" S F: R, S- U' S9 N5 ^ String operator+(const String &str); ! G8 V* V( [: l7 [protected:% d; M5 j* j2 Z2 c char *s;/ z8 q: Z( z8 j7 C int len;6 y7 l1 H8 }% ^. z! n5 T };# O4 f0 J5 h% K( E+ H. ] 6 T* i2 Z* } j" [* R$ r/ p //打印函數 . t% I2 S0 r( B; P5 U* y+ e* zvoid String::prints(), z* O; {& Y$ y7 k+ G9 Y {9 T( R8 q9 b6 W7 l9 T* Y9 i: o% ` int i;6 L% F- p1 w1 e: n0 a for(i=0;i<len;i++) ! X, g0 t! P' G5 |/ e9 w7 _4 ^ cout<<s; 2 q- X4 L# ]# C9 G* b9 G cout<<endl; 6 i1 K2 B" w. z) N} - k) k5 k# V4 h: K/ U( f8 {: \3 J' H' ~% p+ Z8 V/ ^! _7 \+ d //賦值運算符重載$ X: @' r* [7 { ?/ g/ B: u9 @ String& String::operator=(const String &str) $ I* R% V7 A2 H0 {{" n; z. P! a) N6 R delete []s;7 j* ]& ^# k! T$ U% W* q len=str.len;) G* I- X7 V5 ^4 p3 }" l& N s=new char[len]; 8 m6 `- u& H% \ int i;/ ?! K8 G( m+ `. _ for(i=0;i<len;i++) - g* N, U" B" t- L s=str.s; 2 h. k8 _' n# T1 f: [/ D. y4 y return *this; 7 p; n9 C( S+ @4 v4 C* J! _}, b, c) v* U9 R$ u( T" U" y7 C ' v) D3 M9 f9 \8 i//加法運算符重載3 b4 u0 I/ L z- `/ e2 @ inline String String::operator+(const String &str) - C7 X) C" O, A: ?9 u{ " H! X( d1 _" y! t3 I String st(s,len+str.len); ( ]! M+ v& m! ~0 g1 q8 y9 p int i;, N. `1 Q4 }% { for(i=len;i<st.len;i++) ; ^4 a4 v& g% u( ?( E3 P st.s=str.s[i-len]; $ W8 j( }9 q s# y3 a' o1 Z0 {3 s/ H return st; - x8 R/ d. E, V: O8 P} - S7 @; l5 b/ B# B( ^; c) i: f + B5 m& [4 M( d* F! E//拷貝構造函數* T% g9 K# f; G) P& p6 I String::String(const String &str), d$ m: o1 @$ d" t8 g; | { , H5 X2 m4 J# h- H: R# X len=str.len;( q" x/ M. k* y' O' ]6 I( z s=new char[len]; 0 E8 Z ?0 P: c( F% @; S int i; 2 j4 W9 C3 N- G$ r% A j/ @" R for(i=0;i<len;i++) & a. Z: V/ E' o. C s=str.s; ' A* f# q8 i I& I, y( p# O9 {; Z} 2 H% s0 w; i c& V % W( c4 \/ z* Y7 o7 Z9 @//測試+ b7 C) X& x* k0 `0 A int main()5 z5 B+ C0 w: F2 L6 H6 @: N' } {2 }, k1 h: l! r; l8 b. w& Q2 ? char *s1="123"; / U; h: B& |& Z char *s2="4567"; 7 U4 X6 {. ?5 q: i1 z % H& n' B# r6 @ //第一個字符串 9 {5 b$ z# f! e- @- m String str(s1,3);% u- n" V1 x3 Q0 O* f0 g str.prints();1 ^2 a( v0 a, q+ V- M7 K$ L 3 A& O5 \2 Q( ? |: i) J8 w //第二個字符串 / r& ]: ] ~ a/ c) |/ \. w* X String str2(s2,4);& J* P9 ?- f. p- a! I2 I& K Q4 Q str2.prints(); ' r$ j) j) }+ G4 \' _: g! ]7 K5 ^ : @* Z: n1 R; k' h {- l //賦值運算符重載測試+ P6 q% r4 }( c/ i; @ String st; a8 }9 e: a _% ^% I8 y( T st=str; 3 e- {! O/ \. N, \0 r6 i st.prints(); - w' {; c/ q- v* M; j, q2 e; g2 Q5 {" w3 r2 s //加法運算符重載測試 & H7 N% w5 {* j% h& r6 Q4 A( {. b String string; . p J' O/ P6 j. H, c' K' _* ~ string=str+str2;9 a% R A/ T& j& S( Z3 d) X string.prints();0 L: ^" y! {0 l! |0 c3 m ! n- B2 z7 }0 l* Rreturn 0;" _' Q) Q! \. M! c; Q- [" Y# L }. c8 i' _$ z) H3 B7 A ( @% ]# j& H+ m \( r {6 K' {. z% n測試輸出: * m0 ?% `! z1 \+ k: Q, L123 5 B+ L4 N! h. I7 y$ c( s. t4567+ C& i; H' C0 P. i 123 ! V/ g, i s5 c6 K; m6 x |
String 類的原型如下
class String
{
public:
String(const char *str=NULL); //構造函數
String(const String &other); //拷貝構造函數
~String(void); //析構函數
String& operator=(const String &other); //等號操作符重載
ShowString();
String::~String()
{
delete [] m_data; //析構函數,釋放地址空間
}
String::String(const char *str)
{
if (str==NULL)//當初始化串不存在的時候,為m_data申請一個空間存放'\0';
{
m_data=new char[1];
*m_data='\0';
}
else//當初始化串存在的時候,為m_data申請同樣大小的空間存放該串;
{
int length=strlen(str);
m_data=new char[length+1];
strcpy(m_data,str);
}
}
String::String(const String &other)//拷貝構造函數,功能與構造函數類似。
{
int length=strlen(other.m_data);
m_data=new [length+1];
strcpy(m_data,other.m_data);
}
String& String::operator =(const String &other)
{
if (this==&other)//當地址相同時,直接返回;
return *this;
delete [] m_data;//當地址不相同時,刪除原來申請的空間,重新開始構造;
int length=sizeof(other.m_data);
m_data=new [length+1];
strcpy(m_data,other.m_data);
return *this;
}
String::ShowString()//由于m_data是私有成員,對象只能通過public成員函數來訪問;
{
cout<<this->m_data<<endl;
}
main()
{
String AD;
char * p="ABCDE";
String B(p);
AD.ShowString();
AD=B;
AD.ShowString();
}