2022屆應屆生大疆面試經驗分享 | 嵌入式軟件開發工程師


大疆的面試體驗很好(沒有手撕代碼的面試,體驗都很好哈哈哈哈哈)

面試流程

一面

電話面試時間:2021.8.27

自我介紹(1min),項目,大疆業務了解,Linux

二面

視頻面試時間:2021.9.1

自我介紹,項目技術點,項目遇到的難點,大疆產品哪里可以改進,Linux虛擬文件系統

HR面

視頻面試時間:2021.9.18

工作意向,生活經歷等等,不聊技術

offer

時間:2021.10.20

自我介紹

1min和3min各准備一個,隨機應變。

https://www.zhihu.com/question/19603341

我叫xxx,來自xxxx大學xxxxxxx專業,非常高興參加咱們xx公司的面試,我想用3個關鍵詞來介紹自己:
第一個是xxxx,主要講學歷背景
第二個是xxxx,主要講項目經驗
最后一個是xxxx,主要講個人技能及亮點
我對xxxxxx很感興趣, 同時咱們公司是這一行業的龍頭企業,非常感謝有機會參加這次面試。 謝謝!

大疆業務

消費級產品、影像系統、行業應用、教育產品,車載布局

img

Linux相關

Linux內核的組成部分

Linux內核主要由五個子系統組成:進程調度,內存管理,虛擬文件系統,網絡接口,進程間通信。
在這里插入圖片描述

Linux虛擬文件系統

虛擬文件系統(Virtual File System,簡稱VFS)是Linux內核的子系統之一,它為用戶程序提供文件和文件系統操作的統一接口,屏蔽不同文件系統的差異和操作細節。借助VFS可以直接使用open()read()write()這樣的系統調用操作文件,而無須考慮具體的文件系統和實際的存儲介質。

通過VFS系統,Linux提供了通用的系統調用,可以跨越不同文件系統和介質之間執行,極大簡化了用戶訪問不同文件系統的過程。另一方面,新的文件系統、新類型的存儲介質,可以無須編譯的情況下,動態加載到Linux中。

"一切皆文件"是Linux的基本哲學之一,不僅是普通的文件,包括目錄、字符設備、塊設備、套接字等,都可以以文件的方式被對待。實現這一行為的基礎,正是Linux的虛擬文件系統機制。

https://zhuanlan.zhihu.com/p/69289429

Linux系統的組成部分

Linux系統一般有4個主要部分:內核、shell、文件系統和應用程序。
在這里插入圖片描述

Linux的管道原理

管道是一種在兩個進程間進行單向通信的機制。因為管道傳遞數據的單向性,管道又稱為半雙工管道。數據只能由一個進程流向另一個進程(其中一個讀管道,一個寫管道);如果要進行雙工通信,需要建立兩個管道。

管道是由內核管理的一個緩沖區,相當於我們放入內存中的一個紙條。
管道的一端連接一個進程的輸出。這個進程會向管道中放入信息。
管道的另一端連接一個進程的輸入,這個進程取出被放入管道的信息。
一個緩沖區不需要很大一般為4K大小,它被設計成為環形的數據結構,以便管道可以被循環利用。
當管道中沒有信息的話,從管道中讀取的進程會等待,直到另一端的進程放入信息。
當管道被放滿信息的時候,嘗試放入信息的進程會等待,直到另一端的進程取出信息。
當兩個進程都終結的時候,管道也自動消失。

https://segmentfault.com/a/1190000009528245

https://blog.csdn.net/jmppok/article/details/17451261

https://www.cnblogs.com/sallyliu/p/6385806.html

用戶態與內核態

內核態,操作系統在內核態運行——運行操作系統程序

用戶態,應用程序只能在用戶態運行——運行用戶程序

當一個進程在執行用戶自己的代碼時處於用戶運行態(用戶態),此時特權級最低,為3級,是普通的用戶進程運行的特權級,大部分用戶直接面對的程序都是運行在用戶態。3級狀態不能訪問0級的地址空間,包括代碼和數據;當一個進程因為系統調用陷入內核代碼中執行時處於內核運行態(內核態),此時特權級最高,為0級。執行的內核代碼會使用當前進程的內核棧,每個進程都有自己的內核棧。

用戶空間與內核通信方式有哪些?

1)系統調用。用戶空間進程通過系統調用進入內核空間,訪問指定的內核空間數據;

2)驅動程序。用戶空間進程可以使用封裝后的系統調用接口訪問驅動設備節點,以和運行在內核空間的驅動程序通信;

3)共享內存mmap。在代碼中調用接口,實現內核空間與用戶空間的地址映射,在實時性要求很高的項目中為首選,省去拷貝數據的時間等資源,但缺點是不好控制;

4)copy_to_user()、copy_from_user(),是在驅動程序中調用接口,實現用戶空間與內核空間的數據拷貝操作,應用於實時性要求不高的項目中。

段錯誤如何定位?

段錯誤是指訪問的內存超出了系統給這個程序所設定的內存空間,例如訪問了不存在的內存地址、訪問了系統保護的內存地址、訪問了只讀的內存地址、棧溢出等等情況。

段錯誤的調試方法:使用printf輸出信息、使用gcc和gdb、使用core文件和gdb、使用objdump、使用catchsegv

https://blog.csdn.net/jyr6316521/article/details/74390052

bootloader、內核 、根文件的關系

啟動順序:bootloader->linux kernel->rootfile->app

Bootloader全名為啟動引導程序,是第一段代碼,它主要用來初始化處理器及外設,然后調用Linux內核。

Linux內核在完成系統的初始化之后需要掛載某個文件系統作為根文件系統(RootFilesystem),然后加載必要的內核模塊,啟動應用程序。

(一個嵌入式Linux系統從軟件角度看可以分為四個部分:引導加載程序(Bootloader),Linux內核,文件系統,應用程序。)

Bootloader啟動的兩個階段

Stage1:匯編語言

1)基本的硬件初始化(關閉看門狗和中斷,MMU(帶操作系統),CACHE。配置系統工作時鍾)

2)為加載stage2准備RAM空間

3)拷貝內核映像和文件系統映像到RAM中 4)設置堆棧指針sp 5)跳到stage2的入口點

Stage2:C語言

1)初始化本階段要使用到的硬件設備(UART等)
2)檢測系統的內存映射
3)加載內核映像和文件系統映像
4)設置內核的啟動參數

嵌入式系統中廣泛采用的非易失性存儲器通常是Flash,而Bootloader就位於該存儲器的最前端,所以系統上電或復位后執行的第一段程序便是Bootloader。

https://blog.csdn.net/a2145565/article/details/114222971

Linux軟件性能調優

1.系統硬件資源:CPU,多核與超線程

消耗CPU的業務:動態WEB服務,Mail服務器

2.內存:物理內存與swap的取舍,64操作系統

消耗內存的業務:內存數據庫(Redis、hbase、mongodb)

3.磁盤:RAID技術(RAID0/1/5/10),SSD

消耗磁盤的業務:數據庫服務器

4.網絡帶寬:網卡/交換機/雙網卡綁定

消耗帶寬的業務:hadoop平台,視頻業務平台

https://blog.csdn.net/yayaayaya123/article/details/85247850

單片機相關

STM32的一些芯片的配置

CPU主頻:F103系列72MHz,F4系列168MHz;

C8T6:FLASH 64K,RAM 20K;RCT6:FLASH 256K,RAM 48K;ZET6:FLASH 512K,RAM 64K

https://www.cnblogs.com/cai-zi/p/14383210.html

你在stm32上都做過哪些開發?幾個單片機項目

你開發過哪些驅動嗎?屏幕驅動、無線模塊的驅動、GUI開發

SPI、I2C、UART總線

https://www.cnblogs.com/cai-zi/p/14682280.html

你了解整個SPI的通信過程嗎?SPI有幾根線,分別是什么?你使用SPI的時候速率配置的是多少?

SPI是同步全雙工串行通信協議。 SPI通信有4種不同的模式,不同的從設備在出廠就已配置為某種模式,這是不能改變的;但我們的通信雙方必須是工作在同一模式下,所以需要對主設備的SPI模式進行配置,通過CPOL(時鍾極性)和CPHA(時鍾相位)來控制我們主設備的通信模式 。

SPI定義了4根信號線:SCK:時鍾線,主機提供;MISO:主入從出;MOSI:主出從入;SS:片選。

SPI2設置8分頻36MHz/8=4.5MHz

SPI的4種模式

SPI通過時鍾極性CPOL時鍾相位CPHA定義了4種通信模式:

CPOL(時鍾極性)位:控制在沒有數據傳輸時時鍾的空閑狀態電平,此位對主模式和從模式下的設備都有效。

CPHA(時鍾相位):用來配置數據采樣是在第幾個邊沿。

如果CPOL被清’0’, SCK引腳在空閑狀態保持低電平;

如果CPOL被置’1’, SCK引腳在空閑狀態保持高電平。

如果CPHA(時鍾相位)位被置’1’, SCK時鍾的第二個邊沿(CPOL位為0時就是下降沿, CPOL位為’1’時就是上升沿)進行數據位的采樣,數據在第二個時鍾邊沿被鎖存。

如果CPHA位被清’0’,SCK時鍾的第一個邊沿(CPOL位為’0’時就是下降沿, CPOL位為’1’時就是上升沿)進行數據位采樣,數據在第一個時鍾邊沿被鎖存。

I2C總線

開始:SCL為高電平時,SDA有下降沿。

數據傳輸:數據傳輸以字節為單位,第一個字節表示從機地址+讀寫方向,后續數據格式由器件自己定義。數據傳輸中,SDA只能在SCL低電平時變化,並在SCL上升沿進行數據采樣。

應答:每發送一個字節后,接收方必須回復應答信號ACK,但發送最后一個字節后,回復非應答信號NACK。

停止:SCL為高電平時,SDA有上升沿。

說一下SPI和I2C和UART的各自的工作方式優缺點。

SPI同步全雙工,I2C同步半雙工,UART異步全雙工

SPI速度快 協議簡單 但線多; I2C的速度比SPI慢一點,協議比SPI復雜一點,但是連線也比標准的SPI要少;UART距離遠但是只能1對1

img

DMA

直接內存存取技術( Direct Memory Access ), DMA傳輸將數據從一個地址空間復制到另一個地址空間,提供在外設和存儲器之間或者存儲器和存儲器之間的高速數據傳輸。當CPU初始化這個傳輸動作,傳輸動作本身是由DMA控制器來實現和完成的。DMA傳輸方式無需CPU直接控制傳輸,也沒有中斷處理方式那樣保留現場和恢復現場過程,而是通過硬件為RAM和IO設備開辟一條直接傳輸數據的通道,使得CPU的效率大大提高。

在實現DMA傳輸時,是由DMA控制器直接掌管總線,因此,存在着一個總線控制權轉移問題。即DMA傳輸前,CPU要把總線控制權交給DMA控制器,而在結束DMA傳輸后,DMA控制器應立即把總線控制權再交回給CPU。

一個完整的DMA傳輸過程必須經過DMA請求、DMA響應、DMA傳輸、DMA結束4個步驟。

中斷處理流程

請求中斷→響應中斷→關閉中斷→保留斷點→中斷源識別→保護現場→中斷服務子程序→恢復現場→中斷返回。

大型的軟件開發

https://www.bilibili.com/read/cv12937847

經典的軟件開發模型—瀑布模型

img

這個模型把市場與項目緊緊的聯系在一起了,如果一個項目的市場前景很清楚,軟件需求十分明確,那么軟件大多就是采用這種模型進行開發。但是這個開發過程是逐步向下的,那么就會導致軟件后期的維護不方便、軟件的開發周期也很長。

保證項目精准性的模型—V模型

img

該模型最大的特點就是將測試環節貫穿了整個軟件的各個階段,由此達到一種反饋的目的,使得項目的精准性得到很大提高。

快速開發上市的模型—敏捷開發模型

這個模型簡化了開發人員的開發流程、實現快速迭代、循序漸進!簡化開發人員的開發流程體現在不注重各種標准文檔的書寫,注重人的溝通。而快速迭代、循環漸進指的是產品的迭代要快速、分階段進行開發。

以用戶為基礎的模型—原型

原型會先快速構造一個功能模型,演示給用戶看,待用戶確認后再繼續開發。在完善的過程中不斷的演示與用戶溝通。這樣一來就不會出現產品與用戶要求不符合的情況了!這種開發模型最優越的地方就是可以快速定位用戶的需求。

項目分層驅動層、中間層和應用層

底層一般是直接訪問硬件的接口,以串口而言如寄存器操作函數;中間層一般是在底層與上層之間進行數據及信息的轉換,以串口而言如封包/拆包/消息產生/消息響應;應用層就是在很少考慮硬件實現的前提下以通用的方式實現所需的功能,以串口而言如printf。

優點: 開發的快速性、 系統安全性與程序可讀性 、代碼可移植性

嵌入式實時操作系統

FreeRTOS,UCOS,RT-thread,Vxworks等實時系統

軟件開發

容器技術

容器的本質,就是一組受到資源限制,彼此間相互隔離的進程。容器是沒有自己的OS的,直接共享宿主機的內核,也沒有hypervisor這一層進行資源隔離和限制,所有對於容器進程的限制都是基於操作系統本身的能力來進行的,由此容器獲得了一個很大的優勢:輕量化,對應用友好,又具備了一定的隔離性。

https://www.jianshu.com/p/517e757d6d17

中間件

中間件是一種獨立的系統軟件服務程序,分布式應用軟件借助這種軟件在不同的技術之間共享資源,中間件位於客戶機服務器的操作系統之上,管理計算資源和網絡通信。從這個意義上可以用一個等式來表示中間件:中間件=平台+通信,這也就限定了只有用於分布式系統中才能叫中間件,同時也把它與支撐軟件和實用軟件區分開來。

線程調度

各線程間通信

(1)信號量(2)讀寫鎖(3)條件變量(4)互斥鎖(5)自旋鎖

linux中的線程調度

在Linux中,線程是由進程來實現,線程就是輕量級進程( lightweight process ),因此在Linux中,線程的調度是按照進程的調度方式來進行調度的,也就是說線程是調度單元。Linux這樣實現的線程的好處的之一是:線程調度直接使用進程調度就可以了,沒必要再搞一個進程內的線程調度器。在Linux中,調度器是基於線程的調度策略(scheduling policy)和靜態調度優先級(static scheduling priority)來決定那個線程來運行。

https://blog.csdn.net/MaximusZhou/article/details/42042161

單核多線程的系統調度?

一般有這樣兩種模式:分時調度和搶占式調度。

分時調度就是按照順序平均分配;

搶占式調度就是按照優先級來進行分配。

如果現在多個線程,怎么確定哪一個會先被執行?

首先是看優先級,其次看是否處於就緒狀態

進程調度

進程間的通信方式

  1. 管道/匿名管道(Pipes) :⽤於具有親緣關系的⽗⼦進程間或者兄弟進程之間的通信。

  2. 有名管道(Names Pipes) : 匿名管道由於沒有名字,只能⽤於親緣關系的進程間通信。為了克服
    這個缺點,提出了有名管道。有名管道嚴格遵循先進先出(first in first out)。有名管道以磁
    盤⽂件的⽅式存在,可以實現本機任意兩個進程通信。

  3. 信號(Signal) :信號是⼀種⽐較復雜的通信⽅式,⽤於通知接收進程某個事件已經發⽣;

  4. 消息隊列(Message Queuing) :消息隊列是消息的鏈表,具有特定的格式,存放在內存中並由消息
    隊列標識符標識。管道和消息隊列的通信數據都是先進先出的原則。與管道(⽆名管道:只存在
    於內存中的⽂件;命名管道:存在於實際的磁盤介質或者⽂件系統)不同的是消息隊列存放在內
    核中,只有在內核重啟(即,操作系統重啟)或者顯示地刪除⼀個消息隊列時,該消息隊列才會被
    真正的刪除。消息隊列可以實現消息的隨機查詢,消息不⼀定要以先進先出的次序讀取,也可以按
    消息的類型讀取.⽐ FIFO 更有優勢。 消息隊列克服了信號承載信息量少,管道只能承載⽆格式
    字 節流以及緩沖區⼤⼩受限等缺。

  5. 信號量(Semaphores) :信號量是⼀個計數器,⽤於多進程對共享數據的訪問,信號量的意圖在
    於進程間同步。這種通信⽅式主要⽤於解決與同步相關的問題並避免競爭條件。

  6. 共享內存(Shared memory) :使得多個進程可以訪問同⼀塊內存空間,不同進程可以及時看到對
    ⽅進程中對共享內存中數據的更新。這種⽅式需要依靠某種同步操作,如互斥鎖和信號量等。可
    以說這是最有⽤的進程間通信⽅式。

  7. 套接字(Sockets) : 此⽅法主要⽤於在客戶端和服務器之間通過⽹絡進⾏通信。套接字是⽀持
    TCP/IP 的⽹絡通信的基本操作單元,可以看做是不同主機之間的進程進⾏雙向通信的端點,簡
    單的說就是通信的兩⽅的⼀種約定,⽤套接字中的相關函數來完成通信過程。

https://www.jianshu.com/p/c1015f5ffa74

優先級反轉問題

14.進程通信有使用過一些鎖和同步的東西嗎?

15.多個進程在獲取不到鎖的時候會進入什么狀態?
A:阻塞。

16.假設一個低優先的進程A獲取先到鎖,高優先級的進程B獲取不到鎖,那高優先級進程B的進行也會阻塞嗎?
A:還是會阻塞。

17.那如果還有一個任務C,優先級介於A和B之間,那么C任務會去搶占CPU資源嗎?
A:會的.

18.那這樣導致B等待資源的時候會越來越長,這樣的問題有方法可以解決嗎?因為B的優先級才最高。
A:先把A優先級提高,等A釋放后再給B。

19.用什么方式提高A的優先級?
RTOS有函數可以提高。

20.那么A的優先級需要提高到多少?

進程調度算法

(1)先來先服務算法(first-come first-service,FCFS): 只考慮每個作業的等待時間長短

(2)短作業優先調度算法( Shortest Job First,SJF): 只考慮執行時間的長短

(3)高響應比優先調度算法: 對FCFS方式和SJF方式的一種綜合平衡

(4)時間片輪轉法: 讓每個進程在就緒隊列中的等待時間與享受服務的時間成正比例

(5)優先權調度算法(分非搶占和搶占式)

(6)多級反饋隊列調度算法: 輪轉算法和優先級算法的綜合和發展

C語言基礎

程序編譯過程(四個過程)

預處理(Pre-Processing)、編譯(Compiling)、匯編(Assembling)、鏈接(Linking)
  1. 預處理
    讀取C語言源程序,對其中的偽指令(以#開頭的指令)和特殊符號進行處理。
      偽指令主要包括以下四個方面:
      (1)宏定義指令
      (2)條件編譯指令,如#ifdef, #ifndef, #else, #elif, #endif
      (3)頭文件包含指令,如#include “FileName” 或者 #include 等。
      (4)特殊符號,預編譯程序可以識別一些特殊的符號。
      預編譯程序所完成的基本上是對源程序的“替代”工作。經過此種替代,生成一個沒有宏定義、沒有條件編譯指令、沒有特殊符號的輸出文件。這個文件的含義同沒有經過預處理的源文件是相同的,但內容有所不同。下一步,此輸出文件將作為編譯程序的輸出而被翻譯成為機器指令。

  2. 編譯階段
    經過預編譯得到的輸出文件中,將只有常量,如數字、字符串、變量的定義,以及C語言的關鍵字,如main, if, else, for, while, {, }, +, -, *, , 等等。預編譯程序所要做的工作就是通過詞法分析和語法分析,在確認所有的指令都符合語法規則之后,將其翻譯成等價的中間代碼表示或匯編代碼。

  3. 優化階段
    優化處理是編譯系統中一項比較艱深的技術。它涉及到的問題不僅同編譯技術本身有關,而且同機器的硬件環境也有很大的關系。優化一部分是對中間代碼的優化。這種優化不依賴於具體的計算機。另一種優化則主要針對目標代碼的生成而進行的。經過優化得到的匯編代碼必須經過匯編程序的匯編轉換成相應的機器指令,方可能被機器執行。

  4. 匯編過程
    匯編過程實際上指把匯編語言代碼翻譯成目標機器指令的過程。對於被翻譯系統處理的每一個C語言源程序,都將最終經過這一處理而得到相應的目標文件。目標文件中所存放的也就是與源程序等效的目標的機器語言代碼。

  5. 鏈接程序
    由匯編程序生成的目標文件並不能立即就被執行,其中可能還有許多沒有解決的問題。例如,某個源文件中的函數可能引用了另一個源文件中定義的某個符號(如變量或者函數調用等);在程序中可能調用了某個庫文件中的函數,等等。所有的這些問題,都需要經鏈接程序的處理方能得以解決。鏈接程序的主要工作就是將有關的目標文件彼此相連接,也即將在一個文件中引用的符號同該符號在另外一個文件中的定義連接起來。

https://blog.csdn.net/weixin_40756041/article/details/88052207

程序的內存分段

(1)棧(stack):由編譯器自動分配釋放,存放函數的參數值、局部變量的值、返回地址等,其操作方式類似於數據結構中的棧。

棧又稱堆棧, 是用戶存放程序臨時創建的局部變量,也就是說我們函數括弧“{ }”中定義的變量(但不包括static聲明的變量,static意味着在數據段中存放變量)。除此以外,在函數被調用時,其參數也會被壓入發起調用的進程棧中,並且待到調用結束后,函數的返回值也會被存放回棧中。由於棧的先進先出特點,所以棧特別方便用來保存恢復調用現場。從這個意義上講,我們可以把堆棧看成一個寄存、交換臨時數據的內存區。

(2)堆(heap):一般由程序員動態分配(調用malloc函數)和釋放(調用free函數),若程序員不釋放,程序結束時可能由操作系統回收。

堆是用於存放進程運行中被動態分配的內存段,它的大小並不固定,可動態擴張或縮減。當進程調用malloc等函數分配內存時,新分配的內存就被動態添加到堆上(堆被擴張);當利用free等函數釋放內存時,被釋放的內存從堆中被剔除(堆被縮減)。

(3)數據段(data):存放的是常量、常變量(const 變量)、靜態變量、全局變量等。根據存放的數據,數據段又可以分為普通數據段(包括可讀可寫/只讀數據段,存放靜態初始化的全局變量或常量)、BSS數據段(存放未初始化的全局變量)。在采用段式內存管理的架構中,BSS段(bss segment)通常是指用來存放程序中未初始化的全局變量的一塊內存區域。BSS是英文Block Started by Symbol的簡稱。BSS段屬於靜態內存分配。 程序結束后由系統釋放

(4)常量存儲區:常量占用內存,只讀狀態,決不可修改,常量字符串就是放在這里的。

(5)代碼段(code):用於存放程序代碼。代碼段(code segment/text segment)通常是指用來存放程序執行代碼的一塊內存區域。這部分區域的大小在程序運行前就已經確定,並且內存區域通常屬於只讀, 某些架構也允許代碼段為可寫,即允許修改程序。在代碼段中,也有可能包含一些只讀的常數變量,例如字符串常量等。

int a = 0; //全局初始化區
char *p1; //全局未初始化區
main()
{
   int b; //棧中
   char s[] = "abc"; //棧中
   char *p2; //棧中
   char *p3 = "123456"; //123456\0在常量區,p3在棧上
   static int c =0; //全局(靜態)初始化區
   //以下分配得到的10和20字節的區域就在堆區
   p1 = (char *)malloc(10);
   p2 = new char[20];//(char *)malloc(20);
   strcpy(p1, "123456"); //123456\0放在常量區,編譯器可能會將它與p3所指向的"123456"優化成一個地方。
} 

什么是函數指針和指針函數?

指針函數本質是一個函數,其返回值為指針。

函數指針本質是一個指針,其指向一個函數。

指針函數:int* fun(int x,int y);

函數指針:int (*fun)(int x,int y);

https://blog.csdn.net/luoyayun361/article/details/80428882

如何判斷棧溢出?

1、用一個變量記錄棧大小

2、重新設置堆棧指針,指向新的堆棧,並設置堆棧兩端頁面為保護頁面,一旦堆棧溢出,就會產生保護異常

解決的方法:

1、使用虛擬空間
vector存儲數據時,會分配一個存儲空間,如果繼續存儲,該分配的空間已滿,就會分配一塊更大的內存,把原來的數據復制過來,繼續存儲。
2、動態分配:就是不要靜態分配,用new動態創建,是從堆中分配的,堆的空間足夠大,不過記得寫析構函數,delete你申請的堆空間。類結束的時候會自動調用析構函數釋放空間。

一般情況:因為棧一般默認為1-2m,一旦出現死循環或者是大量的遞歸調用,在不斷的壓棧過程中,造成棧容量超過1m而導致溢出。

方法:用棧把遞歸轉換成非遞歸

堆棧指針(SP)

堆棧指針總是指向棧頂位置。一般堆棧的棧底不能動,數據入棧前要先修改堆棧指針,使它指向新的空余空間然后再把數據存進去,出棧的時候相反。

最先入棧的數據要到最后才能出棧,而最后入棧的數據最先出棧。

數據流的Top K問題,所用到的數據結構,以及操作的復雜度

首先以給定數據中的前 K 個數建立小堆,然后從 K+1 個數據開始與堆頂元素作比較,小於或等於堆頂元素時,保持建立的小堆不變;大於堆頂元素時,將該數據與堆頂元素交換,此時有可能破壞了小堆的有序性,需要從堆頂元素開始來一次向下調整使堆恢復成小堆。 基於堆數據結構下的 Top K 問題時間復雜度為:O(N\lg K)

https://blog.csdn.net/z_x_m_m_q/article/details/82389347

如何在main函數之前進行控制台輸出,在C++中如何實現,在C中如何實現

定義在main( )函數之前的全局對象、靜態對象的構造函數在main( )函數之前執行。

可以用main調用main實現在main前執行一段代碼

#include<stdio.h>
#include<stdbool.h>

int main(int argc, char **argv) 
{
	static _Bool firstTime = true;
	if(firstTime) {
		firstTime = false;
		printf("BEFORE MAIN\n");
		return main(argc, argv);
	}

	printf("main\n");

	return 0;
}

C++11中可以用lambda expression

// C++11 
#include <iostream>
int a = []() { 
    std::cout << "a"; 
    return 0; 
}(); 
int main() 
{ 
    std::cout << "b"; 
    return 0; 
}

指針和引用的區別

引用是別名,所以自身沒有空間,那么必須與一個合法的存儲單元關聯,所以定義必須初始化,所以引用不能為空,沒有null引用。

指針是類型,有空間,可以為null,適用於動態分配內存。

(1)指針是實體,引用是別名,沒有空間。

(2)引用定義時必須初始化,指針不用。

(3)指針可以改,引用不可以。

(4)引用不能為空,指針可以。

(5)Sizeof(引用)計算的是它引用的對象的大小,而sizeof(指針)計算的是指針本身的大小。

(6)不能有NULL引用,引用必須與一塊合法的存儲單元關聯。

(7)給引用賦值修改的是該引用與對象所關聯的值,而不是與引用關聯的對象。

(8)如果返回的是動態分配的內存或對象,必須使用指針,使用引用會產生內存泄漏。

(9)對引用的操作即是對變量本身的操作。**
**

https://www.cnblogs.com/yuanqiangfei/category/1392382.html

構造循環鏈表

構造:把尾結點的next指向頭結點。

判斷是否是循環鏈表時,也設置兩個指針,慢指針和快指針,讓快指針比慢指針每次移動快兩次。如果快指針追趕上慢指針,則為循環鏈表,否則不是循環鏈表,如果快指針或者慢指針指向NULL,則不是循環鏈表。

祝大家都能拿到自己心儀的offer!!!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM