騰訊?C ?筆試/面試題及答案
題很多,先上題后上答案,便于大家思考
問題點:
1、C和C 的特點與區(qū)別?
2、C 的多態(tài)
3、虛函數(shù)實現(xiàn)
4、C和C 內存分配問題
5、協(xié)程
6、CGI的了解
7、進程間通信方式和線程間通信方式
8、TCP握手與釋放
9、http和https的區(qū)別?
10、虛擬內存的概念與介紹
11、單鏈表的反轉算法
12、紅黑樹以及其查找復雜度
13、KPM字符串匹配
14、TCP超時等待、重傳以及流量控制
15、數(shù)據(jù)庫引擎
16、數(shù)據(jù)庫索引
1、C和C 的特點與區(qū)別?
答:(1)C語言特點:1.作為一種面向過程的結構化語言,易于調試和維護;2.表現(xiàn)能力和處理能力極強,可以直接訪問內存的物理地址;3.C語言實現(xiàn)了對硬件的編程操作,也適合于應用軟件的開發(fā);4.C語言還具有效率高,可移植性強等特點。(2)C 語言特點:1.在C語言的基礎上進行擴充和完善,使C 兼容了C語言的面向過程特點,又成為了一種面向對象的程序設計語言;2.可以使用抽象數(shù)據(jù)類型進行基于對象的編程;3.可以使用多繼承、多態(tài)進行面向對象的編程;4.可以擔負起以模版為特征的泛型化編程。C 與C語言的本質差別:在于C 是面向對象的,而C語言是面向過程的?;蛘哒fC 是在C語言的基礎上增加了面向對象程序設計的新內容,是對C語言的一次更重要的改革,使得C 成為軟件開發(fā)的重要工具。2、C 的多態(tài)
答:C 的多態(tài)性用一句話概括:在基類的函數(shù)前加上virtual關鍵字,在派生類中重寫該函數(shù),運行時將會根據(jù)對象的實際類型來調用相應的函數(shù)。如果對象類型是派生類,就調用派生類的函數(shù);如果對象類型是基類,就調用基類的函數(shù)。1):用virtual關鍵字申明的函數(shù)叫做虛函數(shù),虛函數(shù)肯定是類的成員函數(shù);2):存在虛函數(shù)的類都有一個一維的虛函數(shù)表叫做虛表,類的對象有一個指向虛表開始的虛指針。虛表是和類對應的,虛表指針是和對象對應的;3):多態(tài)性是一個接口多種實現(xiàn),是面向對象的核心,分為類的多態(tài)性和函數(shù)的多態(tài)性。;4):多態(tài)用虛函數(shù)來實現(xiàn),結合動態(tài)綁定.;5):純虛函數(shù)是虛函數(shù)再加上 = 0;6):抽象類是指包括至少一個純虛函數(shù)的類;純虛函數(shù):virtual void fun()=0;即抽象類,必須在子類實現(xiàn)這個函數(shù),即先有名稱,沒有內容,在派生類實現(xiàn)內容。3、虛函數(shù)實現(xiàn)
答:簡單地說,每一個含有虛函數(shù)(無論是其本身的,還是繼承而來的)的類都至少有一個與之對應的虛函數(shù)表,其中存放著該類所有的虛函數(shù)對應的函數(shù)指針。例:4、C和C 內存分配問題
答:(1)C語言編程中的內存基本構成C的內存基本上分為4部分:靜態(tài)存儲區(qū)、堆區(qū)、棧區(qū)以及常量區(qū)。他們的功能不同,對他們使用方式也就不同。1.棧 ——由編譯器自動分配釋放;2.堆 ——一般由程序員分配釋放,若程序員不釋放,程序結束時可能由OS回收;3.全局區(qū)(靜態(tài)區(qū))——全局變量和靜態(tài)變量的存儲是放在一塊的,初始化的全局變量和靜態(tài)變量在一塊區(qū)域,未初始化的全局變量和未初始化的靜態(tài)變量在相鄰的另一塊區(qū)域(C 中已經(jīng)不再這樣劃分),程序結束釋放;4.另外還有一個專門放常量的地方,程序結束釋放;(a)函數(shù)體中定義的變量通常是在棧上;(b)用malloc, calloc, realloc等分配內存的函數(shù)分配得到的就是在堆上;(c)在所有函數(shù)體外定義的是全局量;(d)加了static修飾符后不管在哪里都存放在全局區(qū)(靜態(tài)區(qū));(e)在所有函數(shù)體外定義的static變量表示在該文件中有效,不能extern到別的文件用;(f)在函數(shù)體內定義的static表示只在該函數(shù)體內有效;(g)另外,函數(shù)中的"adgfdf"這樣的字符串存放在常量區(qū)。(2)C 編程中的內存基本構造在C 中內存分成5個區(qū),分別是堆、棧、全局/靜態(tài)存儲區(qū)、常量存儲區(qū)和代碼區(qū);1、棧,就是那些由編譯器在需要的時候分配,在不需要的時候自動清楚的變量的存儲區(qū),里面的變量通常是局部變量、函數(shù)參數(shù)等。2、堆,就是那些由new分配的內存塊,他們的釋放編譯器不去管,由我們的應用程序去控制,一般一個new就要對應一個delete。如果程序員沒有釋放掉,那么在程序結束后,操作系統(tǒng)會自動回收。3、全局/靜態(tài)存儲區(qū),全局變量和靜態(tài)變量被分配到同一塊內存中,在以前的C語言中,全局變量又分為初始化的和未初始化的,在C 里面沒有這個區(qū)分了,他們共同占用同一塊內存區(qū)。4、常量存儲區(qū),這是一塊比較特殊的存儲區(qū),他們里面存放的是常量,不允許修改(當然,你要通過非正當手段也可以修改)。5、代碼區(qū) (.text段),存放代碼(如函數(shù)),不允許修改(類似常量存儲區(qū)),但可以執(zhí)行(不同于常量存儲區(qū))。內存模型組成部分:自由存儲區(qū),動態(tài)區(qū)、靜態(tài)區(qū);根據(jù)c/c 對象生命周期不同,c/c 的內存模型有三種不同的內存區(qū)域,即:自由存儲區(qū),動態(tài)區(qū)、靜態(tài)區(qū)。自由存儲區(qū):局部非靜態(tài)變量的存儲區(qū)域,即平常所說的棧;動態(tài)區(qū):用new ,malloc分配的內存,即平常所說的堆;靜態(tài)區(qū):全局變量,靜態(tài)變量,字符串常量存在的位置;注:代碼雖然占內存,但不屬于c/c 內存模型的一部分;一個正在運行著的C編譯程序占用的內存分為5個部分:代碼區(qū)、初始化數(shù)據(jù)區(qū)、未初始化數(shù)據(jù)區(qū)、堆區(qū) 和棧區(qū);(1)代碼區(qū)(text segment):代碼區(qū)指令根據(jù)程序設計流程依次執(zhí)行,對于順序指令,則只會執(zhí)行一次(每個進程),如果反復,則需要使用跳轉指令,如果進行遞歸,則需要借助棧來實現(xiàn)。注意:代碼區(qū)的指令中包括操作碼和要操作的對象(或對象地址引用)。如果是立即數(shù)(即具體的數(shù)值,如5),將直接包含在代碼中;(2)全局初始化數(shù)據(jù)區(qū)/靜態(tài)數(shù)據(jù)區(qū)(Data Segment):只初始化一次。(3)未初始化數(shù)據(jù)區(qū)(BSS):在運行時改變其值。(4)棧區(qū)(stack):由編譯器自動分配釋放,存放函數(shù)的參數(shù)值、局部變量的值等,其操作方式類似于數(shù)據(jù)結構中的棧。(5)堆區(qū)(heap):用于動態(tài)內存分配。為什么分成這么多個區(qū)域?主要基于以下考慮:#代碼是根據(jù)流程依次執(zhí)行的,一般只需要訪問一次,而數(shù)據(jù)一般都需要訪問多次,因此單獨開辟空間以方便訪問和節(jié)約空間。#未初始化數(shù)據(jù)區(qū)在運行時放入棧區(qū)中,生命周期短。#全局數(shù)據(jù)和靜態(tài)數(shù)據(jù)有可能在整個程序執(zhí)行過程中都需要訪問,因此單獨存儲管理。#堆區(qū)由用戶自由分配,以便管理。還有騰訊,阿里,京東等一線大廠面試題及答案整理,因篇幅有限,需要集錦的朋友可以 qun720209036免費獲取。
5、協(xié)程
答:定義:協(xié)程是一種用戶態(tài)的輕量級線程。協(xié)程擁有自己的寄存器上下文和棧。協(xié)程調度切換時,將寄存器上下文和棧保存到其他地方,在切回來的時候,恢復先前保存的寄存器上下文和棧。因此:協(xié)程能保留上一次調用時的狀態(tài)(即所有局部狀態(tài)的一個特定組合),每次過程重入時,就相當于進入上一次調用的狀態(tài),換種說法:進入上一次離開時所處邏輯流的位置;線程是搶占式,而協(xié)程是協(xié)作式;協(xié)程的優(yōu)點:跨平臺跨體系架構無需線程上下文切換的開銷無需原子操作鎖定及同步的開銷方便切換控制流,簡化編程模型高并發(fā) 高擴展性 低成本:一個CPU支持上萬的協(xié)程都不是問題。所以很適合用于高并發(fā)處理。協(xié)程的缺點:無法利用多核資源:協(xié)程的本質是個單線程,它不能同時將 單個CPU 的多個核用上,協(xié)程需要和進程配合才能運行在多CPU;進行阻塞(Blocking)操作(如IO時)會阻塞掉整個程序:這一點和事件驅動一樣,可以使用異步IO操作來解決。6、CGI的了解
答:CGI:通用網(wǎng)關接口(Common Gateway Interface)是一個Web服務器主機提供信息服務的標準接口。通過CGI接口,Web服務器就能夠獲取客戶端提交的信息,轉交給服務器端的CGI程序進行處理,最后返回結果給客戶端。CGI通信系統(tǒng)的組成是兩部分:一部分是html頁面,就是在用戶端瀏覽器上顯示的頁面。另一部分則是運行在服務器上的Cgi程序。7、進程間通信方式和線程間通信方式
答:(1)進程間通信方式:# 管道( pipe ):管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關系的進程間使用。進程的親緣關系通常是指父子進程關系。# 信號量( semophore ) :信號量是一個計數(shù)器,可以用來控制多個進程對共享資源的訪問。它常作為一種鎖機制,防止某進程正在訪問共享資源時,其他進程也訪問該資源。因此,主要作為進程間以及同一進程內不同線程之間的同步手段。# 消息隊列( message queue ) :消息隊列是由消息的鏈表,存放在內核中并由消息隊列標識符標識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。# 共享內存( shared memory ) :共享內存就是映射一段能被其他進程所訪問的內存,這段共享內存由一個進程創(chuàng)建,但多個進程都可以訪問。共享內存是最快的 IPC 方式,它是針對其他進程間通信方式運行效率低而專門設計的。它往往與其他通信機制,如信號兩,配合使用,來實現(xiàn)進程間的同步和通信。# 套接字( socket ) :套解口也是一種進程間通信機制,與其他通信機制不同的是,它可用于不同及其間的進程通信。(2)線程間通信方式:#全局變量;#Messages消息機制;#CEvent對象(MFC中的一種線程通信對象,通過其觸發(fā)狀態(tài)的改變實現(xiàn)同步與通信)。8、TCP握手與釋放
答:(1)握手#第一次握手:主機A發(fā)送握手信號syn=1和seq=x(隨機產(chǎn)生的序列號)的數(shù)據(jù)包到服務器,主機B由SYN=1知道,A要求建立聯(lián)機;#第二次握手:主機B收到請求后要確認聯(lián)機信息,向A發(fā)送syn=1,ack=x(x是主機A的Seq) 1,以及隨機產(chǎn)生的確認端序列號seq=y的包;#第三次握手:主機A收到后檢查ack是否正確(ack=x 1),即第一次發(fā)送的seq 1,若正確,主機A會再發(fā)送ack=y 1,以及隨機序列號seq=z,主機B收到后確認ack值則連接建立成功;#完成三次握手,主機A與主機B開始傳送數(shù)據(jù)。注:上述步驟中,第二和第三次確認包中都還包含一個標志位未予以說明,該標志位為1表示正常應答;具體可見圖片:9、http和https的區(qū)別?
答:HTTPS協(xié)議是由SSL HTTP協(xié)議構建的可進行加密傳輸、身份認證的網(wǎng)絡協(xié)議,要比http協(xié)議安全。HTTPS(Secure Hypertext Transfer Protocol)安全超文本傳輸協(xié)議,與http主要區(qū)別在于:#http是超文本傳輸協(xié)議,信息是明文傳輸,https 則是具有安全性的ssl加密傳輸協(xié)議;#http和https使用的是完全不同的連接方式用的端口也不一樣,前者是80,后者是443;下面具體介紹一下HTTP和HTTPS協(xié)議:首先說明一下:HTTP和HTTPS協(xié)議是應用層協(xié)議;HTTPS協(xié)議、SSL、和數(shù)字證書的關系介紹:概述:對于HTTPS協(xié)議,所有的消息都是經(jīng)過SSL協(xié)議方式加密,而支持加密的文件正是數(shù)字證書;(1)SSLSSL常用的加密算法:對稱密碼算法、非對稱密碼算法、散列算法;SSL的加密過程:需要注意的是非對稱加解密算法的效率要比對稱加解密要低的多。所以SSL在握手過程中使用非對稱密碼算法來協(xié)商密鑰,實際使用對稱加解密的方法對http內容加密傳輸;(2)數(shù)字證書數(shù)字證書是用于在INTERNET上標識個人或者機構身份的一種技術手段,它通過由一些公認的權威機構所認證,從而可以保證其安全地被應用在各種場合。證書里面包含了網(wǎng)站地址,加密公鑰,以及證書的頒發(fā)機構等信息。
10、虛擬內存的概念與介紹
答:虛擬內存中,允許將一個作業(yè)分多次調入內存,需要時就調入,不需要的就先放在外存。因此,虛擬內存的實需要建立在離散分配的內存管理方式的基礎上。虛擬內存的實現(xiàn)有以下三種方式:#請求分頁存儲管理#請求分段存儲管理#請求段頁式存儲管理虛擬內存的意義:一,虛擬內存可以使得物理內存更加高效。虛擬內存使用置換方式,需要的頁就置換進來,不需要的置換出去,使得內存中只保存了需要的頁,提高了利用率,也避免了不必要的寫入與擦除;二,使用虛擬地址可以使內存的管理更加便捷。在程序編譯的時候就會生成虛擬地址,該虛擬地址并不是對應一個物理地址,使得也就極大地減少了地址被占用的沖突,減少管理難度;三,為了安全性的考慮。在使用虛擬地址的時候,暴露給程序員永遠都是虛擬地址,而具體的物理地址在哪里,這個只有系統(tǒng)才了解。這樣就提高了系統(tǒng)的封裝性。11、單鏈表的反轉算法
答:思想:創(chuàng)建3個指針,分別指向上一個節(jié)點、當前節(jié)點、下一個節(jié)點,遍歷整個鏈表的同時,將正在訪問的節(jié)點指向上一個節(jié)點,當遍歷結束后,就同時完成了鏈表的反轉。實現(xiàn)代碼:ListNode* ReverseList(ListNode* pHead) {
ListNode *p,*q,*r;
if(pHead==NULL || pHead->next==NULL){
return pHead;
}else{
p=pHead;
q=p->next;
pHead->next=NULL;
while(q!=NULL){
r=q->next;
q->next=p;
p=q;
q=r;
}
return p;
}
}
12、紅黑樹以及其查找復雜度
答:(1)紅黑樹來源于二叉搜索樹,其在關聯(lián)容器如map中應用廣泛,主要優(yōu)勢在于其查找、刪除、插入時間復雜度小,但其也有缺點,就是容易偏向一邊而變成一個鏈表。紅黑樹是一種二叉查找樹,但在每個結點上增加一個存儲位表示結點的顏色,可以是Red或Black。也就是說,紅黑樹是在二叉查找樹基礎上進一步實現(xiàn)的;紅黑樹的五個性質:性質1. 節(jié)點是紅色或黑色;性質2. 根節(jié)點是黑色;性質3 每個葉節(jié)點(指樹的末端的NIL指針節(jié)點或者空節(jié)點)是黑色的;性質4 每個紅色節(jié)點的兩個子節(jié)點都是黑色。(從每個葉子到根的所有路徑上不能有兩個連續(xù)的紅色節(jié)點);性質5. 從任一節(jié)點到其每個尾端NIL節(jié)點或者NULL節(jié)點的所有路徑都包含相同數(shù)目的黑色節(jié)點。(注:上述第3、5點性質中所說的NIL或者NULL結點,并不包含數(shù)據(jù),只充當樹的路徑結束的標志,即此葉結點非常見的葉子結點)。因為一棵由n個結點隨機構造的二叉查找樹的高度為lgn,所以順理成章,二叉查找樹的一般操作的執(zhí)行時間為O(lgn)。但二叉查找樹若退化成了一棵具有n個結點的線性鏈后,則這些操作最壞情況運行時間為O(n);紅黑樹雖然本質上是一棵二叉查找樹,但它在二叉查找樹的基礎上增加以上五個性質使得紅黑樹相對平衡,從而保證了紅黑樹的查找、插入、刪除的時間復雜度最壞為O(log n)。(2)左旋右旋紅黑樹插入或刪除后,一般就會改變紅黑樹的特性,要恢復紅黑樹上述5個性質,一般都要那就要做2方面的工作:1、部分結點顏色,重新著色2、調整部分指針的指向,即左旋、右旋。左選右旋如圖所示:
左旋,如圖所示(左->右),以x->y之間的鏈為“支軸”進行,使y成為該新子樹的根,x成為y的左孩子,而y的左孩子則成為x的右孩子。算法很簡單,旋轉后各個結點從左往右,仍然都是從小到大。左旋代碼實現(xiàn),分三步:(1) 開始變化,y的左孩子成為x的右孩子;(2) y成為x的父結點;(3) x成為y的左孩子;右旋類似,不再累述;
13、KMP字符串匹配
(1)KMP匹配算法代碼實現(xiàn):int KmpSearch(char* s, char* p)
{
int i = 0;
int j = 0;
int sLen = strlen(s);
int pLen = strlen(p);
while (i < sLen