2011年5月10日中兴通讯实习生招聘笔试小记
昨天上午參加了中興通訊2011實習生招聘筆試,我參加的是軟件方向的筆試,試題的難度不大,但是面廣而細,考察了C、C++、數據結構、算法、軟件工程、數據庫、操作系統原理、嵌入式等方面的內容。題目類型有單選、多選,問答和編程題。原以為對C語言比較熟悉,但是經過一考發現疏漏不少,不得不說回歸基礎很重要啊。下面我根據回憶挑選了幾道還有映象的試題分析一下,同時將筆試中的最后兩道編程題回來后上機調試了一下一并貼出來,作為2011年第一次筆試的紀念。
?
選擇題中根據記憶挑選了幾個有代表性的題目:
1、? Switch…Case語句中的參數類型
分析:這個是很基礎的問題,Switch后面括號內的表達式,ANSI標準允許它為任何類型
Case后面括號內的表達式,只能是整型或字符型的常量或常量表達式。
2.???????? 若有說明int i,j,k;則執行i=10;j=20;k=30;k*=i+j后k的值為900。
分析:a*=b相當于a=a*b,所以k*=i+j相當于k=k*(i+j)
3.???????? int i=1;
?????? int j;
?????? j=(i++)+(++i)+(i++);
運算結果為i=4,j=6
分析:雖然自增自減是C語言的基礎語句,但是平時不會有人寫出這么無聊混淆的語句除非它有病。無奈啊,中國的考官就是這么無聊,傷不起啊!!!下面是根據http://topic。csdn。net/u/20100329/23/2fc2d30e-3c79-4f55-ada6-cd7b3bbed3ba。html中復制過來的分析,分析得很好。
? (1)++i表示,i自增1后再參與其它運算;而i++ 則是i參與運算后,i的值再自增1。
? (2)i++的理解應該是執行完整個表達式的其他操作后,然后才自增,++j是先自增然后再參加其它運算。
?
例一:
? int i=3;
? int j=4;
? i++;
? ++j;
? printf("%d, %d/n", i, j);
對此,大家都不會有什么困惑,結果就是 4,5;下面我們來做一點小改動:
? int i=3;
? int j=4;
? int a = i++;
? int b = ++j;
? printf("%d, %d/n", a, b);
結果又是多少呢?這里就開始體現出++前置與后置的區別了,結果是3,5。結合此例,我們回頭再來理解一下“++前置:i自增1后再參與其它運算;++后置:i參與運算后,i的值再自增1”。很明顯,a = i++;由于是先執行賦值運算,再自增,所以結果是a=3,i=4;而b = ++j;
則因先自增,然后再賦值,所以b,j均為5。
其實基本道理就這么簡單了,但在更復雜點的情況下又會如何呢,請看:
例二:
? int i=3;
? int j=4;
? int a = i++ + i++;
? int b = ++j + ++j;
? printf("%d, %d/n", a, b);
問題又來了,i++ + i++是先自增一次,相加,再自增,然后賦值呢,還是先相加賦值然后自增兩次呢。另外,++j又將如何表現呢?
結果是:6,12
這下明白了,原來 i++的理解應該是執行完整個表達式的其他操作后,然后才自增,所以例子中的a=3+3=6;而后i再自增2次,i=5;相反,++j是先自增然后再參加其它運算,所以b=6+6=12。
到此,是否就徹底明了了呢?然后回到引子中的問題:
例三:
? int i=3;
? int j=4;
? int a = i++ + i++ + i++;
? int b = ++j + ++j + ++j;
? printf("%d, %d/n", a, b);
有人可能會說,這很簡單,我全明白了:a=3+3+3=9,i=6,b=5+5+5=15,j=5。真的是這樣嗎?
結果卻是:9,19
這下可好,又糊涂了。對于a = i++ + i++ + i++;我們已經沒有疑問了,++后置就是執行完整個表達式的其他操作后,然后才自增,上例中也得到了驗證,但 b = ++j + ++j + ++j;又該如何理解呢?
原理表達式中除了預算法本身的優先級外,還有一個結合性問題。在++j + ++j + ++j;中,因為存在兩個同級的+運算,根據+運算符的左結合性,在編譯時,其實是先處理前面的(++j + ++j)這部分,然后再將此結果再和++j相加。
例四:
? int i=1;
? int j=1;
? int a = i++ + i++ + i++ + i++ + i++ + i++ + i++; // 七個
? int b = ++j + ++j + ++j + ++j + ++j + ++j + ++j;
? printf("%d, %d/n", a, b);
? printf("%d, %d/n", i, j);
規則就是規則,咱的計算機可不是黑客帝國的母體,總是要遵循它的
a = 1+1+1+1+1+1+1 = 7, i=8
b = 3+3+4+5+6+7+8 = 36, j=8
一切OK,恭喜你還生活在21世紀的地球。注:以上結果及解釋出自VC編譯器,但對于++這個問題是和編譯器的解析有關的,不同廠家可能理解不一致,因手頭沒有其他開發環境,暫無法做全面分析,本文只是為了說明++,--這運算符的一些特性,尤其是前置后置的區別這個問題。類似的問題如果有困惑,最好是寫程序做試驗解決,請勿生搬硬套。謝謝!在實際的編程實踐中,類似的問題除了要試驗搞清外,應該盡量避免引入環境相關的編程技巧。
?
4.???????? 關系數據庫中關系的完整性
a.域完整性
????? 域完整性是對數據表中字段屬性的約束,它包括字段的值域、字段的類型及字段的有效規則等約束,它是由確定關系結構時所定義的字段的屬性決定的。
b.實體完整性
????? 實體完整性是對關系中的記錄唯一性,也就是主鍵的約束。準確地說,實體完整性是指關系中的主屬性值不能為Null且不能有相同值。
c.參照完整性
????? 參照完整性是對關系數據庫中建立關聯關系的數據表間數據參照引用的約束,也就是對外鍵的約束。準確地說,參照完整性是指關系中的外鍵必須是另一個關系的主鍵有效值,或者是NULL。
?
5.???????? GSM中UM接口(具體題目內容不記得了,此處簡要分析)
分析:Um接口被定義為MS(mobile station)與BTS(Base Transceiver Station)之間的通信接口,也稱為無線接口。在所有的GMS接口中,Um接口是最重要的。首先,完善的無線接口實現了各種制造商的移動臺與不同運營商的網絡間的兼容性,從而實現了移動臺的漫游。其次,蜂窩系統的頻譜效率是以關鍵的經濟因素,它完全由無線接口上的傳輸決定。GSM無線傳輸的兩個主要方面是:多址方式和信號處理。很明顯,Um接口實現了MS到GSM系統固定部分的物理鏈接,即無線鏈路,同時它還傳遞了無線資源管理,、移動性管理和接續管理等信息。GSM系統使用類似OSI協議模型的簡化協議,包括物理層(L1)、數據鏈路層(L2)和應用層(L3)。L1是協議模型最底層,提供物理媒介傳輸比特流所需的全部功能。L2保證正確傳遞消息及識別單個呼叫。在GSM系統中,無線接口(Um)上的L1和L2分別是TDMA幀和LAPDm協議。在網絡側,Abis接口和A接口使用的L1均為E1傳輸方式,L2分別為LAPD和MTP協議。在Um接口,MS每次呼叫時都有一個L1和L2層的建立過程,在此基礎上再與網絡側建立L3上的通信。在網絡側(A和Abis接口),其L1和L2(SCCP除外)始終處于連接狀態。L3層的通信消息按階段和功能的不同,分為無線資源管理(RR)、移動性管理(MM)和呼叫控制(CC)三部分。
?
6.???????? static變量相關(考了幾個題目,具體題目不記得了,下面對static用法做個總結)
(1)?????? 修飾變量:
靜態全局變量:作用域僅限于被定義的文件中,其他文件即使使用extern聲明也沒法使用,準確的說:作用域是從定義之處開始,到文件結尾處結束,在定義之處前面的那些代碼行也不能使用它,要想使用就得在前面再加extern。
靜態局部變量:在函數體里面定義,就只能在這個函數里用了,同一個文檔中的其他函數也用不了。
(2)? 修飾函數:函數的作用域僅局限于本文件。
?
問答題:
1、? 進程和線程的區別:
進程是具有一定獨立功能的程序關于某個數據集合上的一次運行活動,進程是系統進行資源分配和調度的一個獨立單位。線程是進程的一個實體,是CPU調度和分派的基本單位,它是比進程更小的能獨立運行的基本單位。線程自己基本上不擁有系統資源,只擁有一點在運行中必不可少的資源(如程序計數器,一組寄存器和棧),但是它可與同屬一個進程的其他的線程共享進程所擁有的全部資源。
一個程序至少有一個進程,一個進程至少有一個線程。
進程有自己獨立的地址空間,一個進程崩潰后,在保護模式下不會對其他的進程產生影響,而線程只是一個進程中的不同執行路徑,線程有自己的堆棧和局部變量,但線程之間沒有單獨的地址空間,一個線程死掉就等于整個進程死掉,所以多進程程序要比多線程程序健壯,但在進程切換時耗費資源較大,效率要差一些,但對于某些要求同時進行且要共享某些變量的并發操作,不能用進程。
?
2、? 中斷服務程序的原理
保護現場->中斷處理->恢復現場
?
3、? 簡述Stack Frame,并畫出當函數A調用函數B時A和B各自的堆棧布局圖
分析:筆試時此題知道概念描述不清楚,現在好好理一下。
大多數CPU上的程序實現使用棧來支持函數調用操作。棧被用來傳遞函數參數、存儲返回信息、臨時保存寄存器原有值以備恢復以及用來存儲局部數據。單個函數調用操作所使用的棧部分被稱為棧幀結構,棧幀結構的兩端有兩個指針來指定。寄存器ebp通常用作幀指針,而esp則用作棧指針。在函數執行過程中,棧指針esp會隨著數據的入棧和出棧而移動,因此函數中對大部分數據的訪問都基于幀指針ebp進行。設在函數A中調用函數B,函數B中有兩個形參m,n,則棧幀結構如下圖:
調用之前:
?
?
調用之后:
?
?
兩道編程題
1、? 編寫函數實現鏈表反轉:
Struct node
{
?????? int data;
?????? struct node *next;
}
typedef struct node Node;已知頭結點head。
程序實現:該題的原題是微軟早年的經典面試題
Node* ReverseIteratively(Node* pHead) {Node* pReversedHead = NULL;Node* pNode = pHead;Node* pPrev = NULL;while(pNode != NULL){// get the next node, and save it at pNextNode* pNext = pNode->Next;// if the next node is null, the currect is the end of original // list, and it's the head of the reversed listif(pNext == NULL)pReversedHead = pNode;// reverse the linkage between nodespNode->pNext = pPrev;// move forward on the the listpPrev = pNode;pNode = pNext;}return pReversedHead; }
2、??? 用遞歸法實現整型數到字符串的轉換,例如:輸入1234,轉換后得到“1234”,輸入整數的范圍不超過5位。
?
程序實現:
#include <stdio.h> #define M 6void intToString(char *p,int origin) {if(origin/10==0){p[0]=origin%10+'/0';}else{intToString(p+1,origin/10);}}int main() {char s[M];int i;scanf("%d",&i);if(i>65535||i<-65535)return -1;intToString(&s[0],i);printf("/n%s",s); return 0; }
總結
以上是生活随笔為你收集整理的2011年5月10日中兴通讯实习生招聘笔试小记的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 越野车分类
- 下一篇: 20180310华为面试