嵌入式經典筆試題

1、堆和棧的區別

堆上的空間是手動分配和釋放的,棧上的空間是自動分配與釋放的。

棧空間是有限的,堆空間是很大的自由儲存區

 

2、全局變量與局部變量的區別

  • 作用域不同:全局變量作用域爲整個程序,局部變量作用域爲當前語句塊。
  • 內存存儲方式:全局變量在全局數據區,局部變量儲存在棧上。
  • 生命週期不同:全局變量的生命週期跟程序一樣,局部變量隨着語句塊的結束而結束。
  • 當局部變量和全局變量同名時,優先使用局部變量,使用全局變量要用域成員運算符。

 

3、結構體與聯合的區別

  • 結構體與聯合都是由不同的數據類型組成,但在任何時刻,聯合只存在一個被選中成員,結構體的所有成員都存在。
  • 在結構體中,各成員佔有自己的存儲空間,總大小等於各成員大小之和
  • 在聯合中,所有成員共用一塊存儲空間,其大小等於聯合中最大的成員的大小

 

4、數組與指針的區別

  • 數組要麼在靜態儲存區,要麼在棧上被創建。數組名對應着一塊內存,其容量與地址在生命週期內保持不變
  • 指針可以隨時指向任意類型的內存塊,它的特徵是可變。比數組靈活,但也危險

 

5、指針函數與函數指針的區別

指針函數是一個函數,它返回值是一個指針。

函數指針是一個指針,這個指針所指的對象是一個函數

 

6、常量與變量的區別

常量是隻讀不可寫,變量可讀可寫;常量必須初始化,變量可以不初始化

常量不可以尋址,它的地址不可以賦給非常量指針。變量可以尋址;常量的效率比變量高

 

7、指針自增自減與變量自增自減有什麼區別

指針自增自減是改變指針所指的對象。變量自增自減是改變變量的值

 

8、#error的作用是什麼

編譯程序時,只要遇到#error就會跳出一個編譯錯誤

 

9、#include<file.h>和#include "file.h"的區別

#include<file.h>表示該文件存在編譯器指定的標準頭文件存放處

#include "file.h" 表示該文件在用戶當前的工作目錄下

 

10、頭文件中的 ifndef/define endif 的作用

防止頭文件被重複引用

 

11、常見的條件語句的比較的寫法

  • bool類型 if(flag)建議使用 ; if(flag == true) 不建議使用,true值的定義沒有統一的標準
  • int if(value != 0)建議使用;if(value)不建議使用,會讓人誤認爲是bool類型
  • float if(x>-EPSINON && x<EPSINON)建議使用;if(x == 0.0)不建議使用,精度問題
  • 指針 if(p == NULL)建議使用,強調p爲指針;if(p==0)不建議使用,會讓人誤解爲int類型

 

12、用#define實現宏並求最大值最小值

#define MAX(x, y) ((x)>(y))?(x):(y)

#define MIN(x, y) ((x)<(y))?(x):(y)

 

13、break語句與continue語句有什麼區別

continue語句只能出現在循環語句內,表示結束本次循環;break語句還可以出現在switch語句內,表示結束switch語句,在循環語句內表示結束整個循環

 

14、static關鍵字

  • 用於全局變量:表示該變量是靜態全局變量。作用域爲當前文件
  • 用於函數:該函數爲靜態函數,只能在本文件中調用。靜態函數在內存中只有一份,普通函數在內存中維持一份拷貝
  • 用於局部變量:爲靜態局部變量,只初始化一次,之後調用函數都是上次函數退出的值。即改變變量的生存週期爲整個程序運行時間段內
  • static成員函數:表示這個函數屬於此而不屬於此類的任何對象,不能訪問非靜態變量和函數,該函數在該類中是唯一的
  • static成員變量:表示該變量屬於此類而不屬於此類的任何對象,該變量的初始化在類體外

 

15、const關鍵字

  • 修飾一般常量:修飾符可在類型說明符前,也可在類型說明符後,
    • 例如:int const x=2; const int x = 2;
  • 修飾數組: 修飾符 const 可以用在類型說明符前,也可以用在類型說明符後。
    • 例如列如: int const a[5]={1, 2, 3}; 或: const int a[5]={1, 2, 3};
  • 修飾常指針
    • const int *A;//const 修飾指針指向的對象,指針可變,指針指向的對象不可變
    • int const *A;//const 修飾指針指向的對象,指針可變,指針指向的對象不可變
    • int *const A; //const 修飾指針, 指針不可變,指針指向的對象可變

 

16、const 與宏的區別

答:

編譯時刻 宏:在預編譯時刻 const:在編譯時刻

編譯檢查 宏不會編譯檢查 const:有編譯檢查

宏的好處: 宏可以定義函數、方法等等 const:不可以

宏的壞處: 大量使用宏,會導致預編譯的時間過長

 

17、帶參宏與函數的區別

答:

  • 1、 處理時間不同: 宏是在預編譯時刻,函數是在運行時刻。
  • 2、 帶參宏沒有參數類型,函數具有參數類型。
  • 3、 帶參宏不分配內存,函數需要分配內存。
  • 4、 宏會使函數邊長,函數不會。
  • 5、 宏不佔用運行時間,函數在調用時刻和返回時刻佔用時間。

 

18、局部變量與全局變量有什麼區別

答:局部變量儲存在棧區,全局變量儲存在靜態數據區。

 

19、引用與指針的區別

答:

  • 1、 非空區別:指針可以指向 NULL,引用必須指向某個對象。
  • 2、 可修改區別:指針可以指向不同的對象,引用總是指向初始化的對象
  • 3、 合法性區別:在使用指針之前要判斷指針是否爲 NULL,引用不需要判斷

 

20、malloc()和 calloc()的區別

  • 1、 malloc 和 colloc 都是在堆上申請動態內存空間。
  • 2、 malloc 只有一個參數,即要分配內存大小
  • 3、 calloc 函數有兩個參數,分別是元素的個數與元素的大小。
  • 4、 malloc 不能對內存初始化, calloc 對內存的沒一位初始化爲零

 

21、strcpy sprint memcpy 函數的區別

答: strcpy 函數操作的對象是字符串 ,完成從源字符串到目的字符串的拷貝

sprint 函數操作的對象不限於字符串,是實現其它數據類型吸納高字符串的轉化。 方法中需要指定源對象的數據類型,如果源對象是字符串,也可以實現字符串的拷貝功能。

memcpy 內存的拷貝,實現將一個內存的內容複製到另一個內存塊。內存塊由首地址及長度決定。

 

22、strcpy 函數爲什麼要返回 char*類型

答:增加代碼的靈活性,方便其它函數直接調用。

 

23、new delete 與 malloc free 的聯繫與區別

答:

  • 1、 都是在堆上進行動態內存的分配與釋放。
  • 2、 new delete 是 c++的運算符, malloc free 是函數
  • 3、 new 會自動調用對象的構造函數,返回相應的類型。
  • 4、 malloc 只會申請指定大小的內存,返回 void*類型(不能初始化對象)。
  • 5、 delete 與 new 配對,會調用析構函數。
  • 6、 free 與 malloc 配對,只是內存的釋放,不會調用析構函數。

 

24、關於靜態內存的分配和動態內存的分配的區別及過程

  • 1、 靜態內存的分配是在編譯時刻完成的,不佔用 CPU 資源;動態分配內存是在運行時刻完成,分配與
  • 釋放佔用 CPU 運行時間,
  • 2、 靜態內存分配是在棧上的,動態內存是在堆上分配的。
  • 3、 動態內存分配需要指針或引用數據類型的支持,而靜態內存分配不需要。
  • 4、 靜態內存的分配是按計劃分配的,在編譯前確定內存塊大小,動態內存分配運行時按需分配。
  • 5、 靜態內存的分配是把內存的控制權交給了編譯器,動態內存的分配是把內存的分配交給了程序員。
  • 6、 靜態分配內存的效率比動態分配內存的效率高,因爲動態內存的分配與釋放需要額外的開銷;動態內存管理水平嚴重依賴於程序員的水平,處理不當容易造成內存泄露。

 

25、一個短小的函數在 C 和 C++中分別用什麼實現

答:在 C++中用內聯函數實現,在 C 中用宏實現。

 

26、在 c++程序中調用被 C 編輯器變異後的 函數,爲什麼要加 extern C?

答: c++語言支持函數的重載, c 語言不支持函數的重載。編譯後參數的名字不同,函數被 c++編譯器編譯後產生的名字爲函數名加參數列表類型名之類的名字。而 c 編輯器編譯後產生的名字爲函數名。

 

27、一個由 C/C++編譯器編譯過的程序有那幾個部分

答:

  • 1、 棧區:由編譯器自動編譯,釋放;儲存函數參數的值,局部變量的值等。其操作方式類似於數據結構中的棧
  • 2、 堆區:由程序員分配與釋放,如果程序員沒有釋放在程序結束時可能由 OS 釋放,儲存結構類似於鏈表。
  • 3、 全局區全局變量和靜態變量儲存在這一塊,初始化的全局變量與靜態變量在一塊,未出貨的全局變量存放在靜態變量相鄰的一塊。程序結束後由系統釋放。
  • 4、 文字常量區 常量字符串存放在此處,程序結束後系統自動釋放
  • 5、 程序代碼區:存放函數體的二進制代碼

 

28、C 與 C++有什麼區別

答: C 語言是面向結構化的編程語言,他是面向過程的, C 語言編程考慮的是實現的過程; C++是面向對象的, C++編程考慮的是整個程序的模型。

 

29、虛析構函數與析構函數的區別

答: 加上 virtual 後,就會先執行子類的析構函數, 再執行基類的析構函數。

不執行析構函數,就可能存在內存泄露。

 

30、面向對象與面向過程的區別

答:面向對象是一種以對象爲中心的編程思想,以消息進行驅動,程序 = 對象 + 消息;

面向過程是一種以應用爲中心的編程思想,以算法進行驅動,程序 = 算法 + 數據

 

31、“extern c”的作用

答: extern c 是告訴編譯器這段代碼以 C 語言進行編譯

 

32、類成員函數的重載,重寫,隱藏的區別

答:

重載:在一個類中,方法名相同,參數列表不同。與 virtual 無關

重寫:也叫覆蓋 指在子類中定義一個與父類中的虛函數並且實現。

隱藏:派生類函數與基類函數名相同,但參數不同。或者參數相同但父類不是虛函數。

 

33、多態的實現?

答:簡單的說是子類實現了父類的虛函數,父類指針不僅可以調用自己的這個函數,當指向子類時可以調用子類的這個函數,從而實現了多態。

 

34、多態的作用?

答:實現了動態聯編, 使程序的運行效率更高,更容易維護。

 

35、默認的拷貝構造函數的缺陷

答:存在着淺拷貝問題,主要是在內中定義指針變量時,當調用默認拷貝構造函數時,只拷貝地址,兩個對象的指針變量指向同一塊地址空間。

 

36、簡述成員函數、全局函數、友元函數的區別

成員函數只能由實例化對象調用(靜態成員函數除外)全局函數可在任何時刻調用,

友元函數可以讓類的友元類對象調用。(友元類或函數可以訪問私有成員函數和變量)。

 

37、什麼時候會使用複製(拷貝)構造函數

答 :

1、 一個對象以值的方式傳入函數體

2、 一個對象以值傳遞的方式重函數中返回

3、 一個對象需要通過另外一個對象初始化

 

38、什麼是容器

答:容器是存放特定對象的集合,在 STL 中有順序容器和關聯容器兩種。

 

39、什麼是順序容器,有那幾種

答:順序容器是指將一組具有相同類型的對象,以嚴格的線性形式組織在一起的容器。包括 vector、deque、list 等 3 種順序容器。

 

40、什麼是關聯容器,有哪幾種

答:關聯容器可以通過鍵值對來查找和讀取元素的容器,在 STL 中有四個關聯容器,分別是: map、 set、multimap、 multiset。

 

41、什麼是異常

答:異常就是程序運行時出現的不正常,它可能會導致系統無法正常運行甚至停止運行等嚴重的情況

 

42、如何拋出異常

答:在 C++中,系統通過 try 快和異常處理構成異常處理機制,其中通過 catch 語句來捕獲運行時的異常,並且執行異常處理,通過 throw 語句來拋出異常

 

43、軟件測試的方法有那幾類

答:兩類,黑盒:針對系統功能做測試,白盒:測試函數的功能

 

44、TCP 與 UDP 的區別

TCP

 

面向連接

 

數據是安全的

 

效率低

 

基於數據流

 

可靠

UDP

 

面向無連接

 

數據是不安全的

 

效率高

 

基於數據報文

 

不可靠

 

45、TCP/IP 協議的主要層次結構

應用層、 傳輸層、 網絡層、 數據鏈路層、 物理層

 

46、epoll 的 LT,ET 模式

二者的差異在於 level-trigger 模式下只要某個 socket 處於 readable/writable 狀態,無論什麼時候進行

epoll_wait 都會返回 socket;而 edge-trigger 模式下只有某個 socket 從 unreadable 變爲 readable 或

從 unwritable 變爲writable 時, epoll_wait 纔會返回 socket。

 

47、三次握手

答:三次握手即建立 TCP 連接,就是指建立一個 TCP 連接時,需要客戶端和服務端發送 3 個包以確認連

接的建立。在 socket 編程中,這一過程由客戶端指向 connect 來出發。

1)第一次握手:建立連接時,客戶端發送syn包(syn=x)到服務器,並進入SYN_SENT狀態,等待服務器確認;SYN:同步序列編號(Synchronize Sequence Numbers)。

2)第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=x+1),同時自己也發送一個SYN包(syn=y),即SYN+ACK包,此時服務器進入SYN_RECV狀態;

3)第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發送確認包ACK(ack=y+1),此包發送完畢,客戶端和服務器進入ESTABLISHED(TCP連接成功)狀態,完成三次握手。

48、四次揮手

答: 四次揮手是終止 TCP 連接,就是指端口一個 TCP 連接時,需要客戶端和服務端發送四個包以確認連接的斷開,在 socket 編程中,這一過程由客戶端或服務端任意一方執行 close 來觸發。

 1)第一次揮手:Client發送一個FIN,用來關閉Client到Server的數據傳送,Client進入FIN_WAIT_1狀態。

 2)第二次揮手:Server收到FIN後,發送一個ACK給Client,確認序號爲收到序號+1(與SYN相同,一個FIN佔用一個序號),Server進入CLOSE_WAIT狀態。

 3)第三次揮手:Server發送一個FIN,用來關閉Server到Client的數據傳送,Server進入LAST_ACK狀態。

 4)第四次揮手:Client收到FIN後,Client進入TIME_WAIT狀態,接着發送一個ACK給Server,確認序號爲收到序號+1,Server進入CLOSED狀態,完成四次揮手

49、爲什麼建立連接是三次握手,關閉連接卻是四次揮手

答: 這是因爲服務端在 LISTEN 狀態下,收到建立連接請求的 SYN 報文後,把 ACK 和 SYN 放在一個報

文裏發送給客戶端。而關閉連接時,當收到對方的 FIN 報文時,僅僅表示對方不再發送數據了但是還能接

收數據,己方也未必全部數據都發送給對方了,所以己方可以立即 close,也可以發送一些數據給對方後,

再發送 FIN 報文給對方來表示同意現在關閉連接,因此,己方 ACK 和 FIN 一般都會分開發送。

 

50、進程與線程的區別

答:線程是進程的一個執行單元,也是進程可以調度的實體。與進程的區別:

(1)線程是調度和分配分配的基本單位,進程時擁有資源的基本單位。

(2)進程可以併發執行,同一進程的多個線程也可以併發執行。

(3)進程是擁有資源的獨立單位,線程不擁有系統資源,但可以訪問進程的資源。

(4)在創建進程時,系統要爲之分配和回收資源,導致系統的開銷明顯大於創建或撤銷線程的開銷。

歸納:進程有用獨立的資源、有PCB;線程有獨立PCB,但沒有獨立的資源,可以與同進程的其它線程共享數據。

51、TCP/UDP工作在哪一層?

答:傳輸層

 

52、tcp/udp的使用場合?

(1)對數據可靠性的要求。tcp適用於可靠性高的場合,udp適用於可靠性低的場合

(2)應用的實時性。tcp有延時較大,udp延時較小

(3)網絡的可靠性。網絡不好的情況下使用tcp,網絡條件好的情況下,使用udp

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章