圖吧導航引擎組2017校招電面總結

寫在圖吧導航引擎組電面之後

今天上午10點左右圖吧導航引擎組IOS崗打電話面試,本人蔘加的是2017校招,所以簡歷篩選過後,先給的電面。目前面試結果尚不得而知,面試的過程還是很nice的,電面是個女面試官,在我回答不上來的時候也着意去引導一下我。剛開始,先談了談我自己自學IOS的過程,以及實習的經歷還有在校學習iOS的過往,還有他們公司的產品以及發展方向。之前對他們公司還是有所瞭解,最爲誘人的還是工資待遇,月薪16K起,special offer 20K起。廢話不多說,下面總結一下此次電面的題目。

題目:
一.談談你對C/C++的預處理命令的瞭解

預處理是在程序編譯之前進行的處理,C語言的預處理主要有三個方面的內容:1.宏定義、2文件包含、3.條件編譯、4.佈局控制;預處理命令以符號“#”開頭。

1.宏定義:又稱宏代換、宏替換。預處理也叫宏展開:將宏名替換爲文本。

(1).不帶參數的宏定義:格式:#define 宏名 文本。例:#define PI 3.1415926 把程序中全部的標識符PI換成3.1415926。
說明:1.宏名一般大寫、2.使用宏可提高程序的通用性和易讀性,減少錯誤和便於修改。
(2).帶參數的宏:格式:#define 宏名(參數表) 文本 例:#define S(a,b) a*b area=S(3,2); 第一步被換爲area=a*b,第二步被換爲area=3*2; 類似於函數調用。
說明:1.宏替換隻做替換,不做計算,不做表達式求解。2.宏替換在編譯前進行,不分配內存,函數調用要分配內存。3.宏展開不佔運行時間,只佔編譯時間,函數調用佔運行時間(分配內存,值傳遞等)

2.文件包含:一個文件包含另一個文件的內容
格式:#include”文件名”或#include<文件名>
例:#include”iostream” 或 #include
區別:前者是編譯器從用戶的工作路徑開始搜索,後者是編譯器從標準庫路徑開始搜索。

3.條件編譯:有些語句希望在條件滿足時才編譯。
格式:(1)

#ifdef 標識符
程序段1
#else
程序段2
#endif#ifdef
程序段1
#endif

當標識符已經定義時,程序段1才參加編譯。
格式:(2)

#ifndef 標識符
#define 標識1
程序段1
#endif

如果標識符沒有被定義,則重定義標識1,且執行程序段1。
格式:(3)

#if 表達式1
程序段1
#elif 表達式2
程序段2
……
#elif 表達式n
程序段n
#else
程序段n+1
#endif

當表達式1成立時,編譯程序段1,當不成立時,編譯程序段2。

使用條件編譯可以使目標程序變小,運行時間變短。
預編譯使問題或算法的解決方案增多,有助於我們選擇合適的解決方案。

4.佈局控制:#pragma;
這也是我們應用預處理的一個重要方面,主要功能是爲編譯程序提供非常規的控制流信息。

二、說一下你對堆棧的認識,說的比較細一點
堆棧是兩種數據結構,都是一種數據項按序排列的數據結構,只能在一端對數據項進行插入和刪除。
在數據結構角度看是兩種不同的數據結構:
堆:隊列優先,先進先出;
棧:先進後出;
在操作系統角度看是兩種不同的內存分配方式:
棧區:由操作系統自動分配釋放內存,存放函數的參數值、局部變量值等;
堆區:一般由程序員分配釋放內存,是一種動態分配內存(詳見下面2.2部分),若程序員不釋放,程序結束時由垃圾回收機制回收。(在C/C++中如果不釋放可能會導致內存不足,要養成好的申請釋放的習慣,C中malloc申請,free釋放。C++中new申請,delete釋放;在Java中有垃圾回收機制,自動回收多餘內存。)


堆和棧的理論知識
2.1申請方式
stack:
由系統自動分配。 例如,聲明在函數中一個局部變量 int b; 系統自動在棧中爲b開闢空

heap:
需要程序員自己申請,並指明大小,在c中malloc函數
如p1 = (char *)malloc(10);
在C++中用new運算符
如p2 = new char[10];
但是注意p1、p2本身是在棧中的。

2.2
申請後系統的響應
棧:只要棧的剩餘空間大於所申請空間,系統將爲程序提供內存,否則將報異常提示棧溢出。
堆:首先應該知道操作系統有一個記錄空閒內存地址的鏈表,當系統收到程序的申請時, 會遍歷該鏈表,尋找第一個空間大於所申請空間的堆結點,然後將該結點從空閒結點鏈表中刪除,並將該結點的空間分配給程序,另外,對於大多數系統,會在這塊內存空間中的首地址處記錄本次分配的大小,這樣,代碼中的delete語句才能正確的釋放本內存空間。
另外,由於找到的堆結點的大小不一定正好等於申請的大小,系統會自動的將多餘的那部分重新放入空閒鏈表中。

2.3申請大小的限制
棧:在Windows下,棧是向低地址擴展的數據結構,是一塊連續的內存的區域。這句話的意思是棧頂的地址和棧的最大容量是系統預先規定好的,在WINDOWS下,棧的大小是2M(也有的說是1M,總之是一個編譯時就確定的常數),如果申請的空間超過棧的剩餘空間時,將提示overflow。因此,能從棧獲得的空間較小。
堆:堆是向高地址擴展的數據結構,是不連續的內存區域。這是由於系統是用鏈表來存儲的空閒內存地址的,自然是不連續的,而鏈表的遍歷方向是由低地址向高地址。堆的大小受限於計算機系統中有效的虛擬內存。由此可見,堆獲得的空間比較靈活,也比較大。

2.4申請效率的比較:
棧由系統自動分配,速度較快。但程序員是無法控制的。
堆是由new/malloc分配的內存,一般速度比較慢,而且容易產生內存碎片,不過用起來最方便.
/另外,在WINDOWS下,最好的方式是用VirtualAlloc分配內存,他不是在堆,也不是在棧是直接在進程的地址空間中保留一塊內存,雖然用起來最不方便。但是速度快,也最靈活。 /

2.5堆和棧中的存儲內容
棧: 在函數調用時,第一個進棧的是主函數中後的下一條指令(函數調用語句的下一條可執行語句)的地址,然後是函數的各個參數,在大多數的C編譯器中,參數是由右往左入棧的,然後是函數中的局部變量。注意靜態變量是不入棧的。 當本次函數調用結束後,局部變量先出棧,然後是參數,最後棧頂指針指向最開始存的地址,也就是主函數中的下一條指令,程序由該點繼續運行。
堆:一般是在堆的頭部用一個字節存放堆的大小。堆中的具體內容由程序員安排。

2.6存取效率的比較
char s1[] = “aaaaaaaaaaaaaaa”;
char *s2 = “bbbbbbbbbbbbbbbbb”;
aaaaaaaaaaa是在運行時刻賦值的;
而bbbbbbbbbbb是在編譯時就確定的;
但是,在以後的存取中,在棧上的數組比指針所指向的字符串(例如堆)快。

//C或C++程序中佔內存的幾個模塊:棧區、堆區、全局/靜態區、文字常量區、程序代碼區; 以上佔內存的模塊,除了堆以爲,其他都是程序結束後系統自動釋放。

2.7小結:
堆和棧的區別可以用如下的比喻來看出:
使用棧就象我們去飯館裏吃飯,只管點菜(發出申請)、付錢、和吃(使用),吃飽了就走,不必理會切菜、洗菜等準備工作和洗碗、刷鍋等掃尾工作,他的好處是快捷,但是自由度小。
使用堆就象是自己動手做喜歡吃的菜餚,比較麻煩,但是比較符合自己的口味,而且自由度大。

三、你對虛擬內存瞭解多少
答:虛擬內存就是劃出一部分硬盤來當內存使用,在虛擬空間中實際要使用的內存大於物理內存時,就會用到虛擬內存。舉個例子:假如你的電腦內存是512M的,現在你需要執行一個1G的內存,很明顯你的物理內存並沒有足夠的空間去執行這個進程,那就得需要使用虛擬內存。然後映射的時候,你的物理內存除去系統需要佔用的空間,剩下也就300M,那就會先映射這300M的內存,其餘的再去虛擬內存中映射。虛擬內存的設置在我的電腦->屬性->高級設置->虛擬內存中設置大小,一般是實際物理內存的1.5-3倍。
進程一般會採取分頁技術,分成大小一樣的很多頁,每頁有編號.然後頁表裏面會把你每頁對應內存中具體的一塊內存.當超過那300的實際上就對應於虛擬內存中去了.(實際上就是硬盤上的一個swp文件),肯定也有標誌信息表明這部分是在硬盤上. 於是當進程運行起來時,需要用到某個地址時就映射到虛擬內存中時就會出現所謂的缺頁,那頁不在內存中嘛,於是就需要去硬盤上把數據讀進內存來,如果內存滿了就需要置換出去一些頁. 所以你設置了虛擬內存,最後如果真的會有用到,那你會看到硬盤轉的很快,然後程序運行速度會變慢.硬盤的操作比內存慢很多

四、線程和進程的區別(應屆生招聘常問問題,還有多線程)

進程: 是一個動態的概念,是併發執行的程序在執行過程中操作系統進行資源分配和調度基本單位。每一個進程都有自己的一個地址空間,進程空間的大小與處理機的位數有關。

線程:線程是進程的一個實體,是進程的一部分,它是比進程更小的能獨立運行的基本單位,是CPU調度和分派的基本單位,一個沒有線程的進程可以被看做單進程。線程基本上不擁有系統系統資源,只有一點運行中必不可少的資源(程序計數器、棧等),但是他與同屬一個進程的其他線程共享進程所擁有的全部資源。

進程和線程的關係:

(1)一個線程只能屬於一個進程,而一個進程可以有多個線程,但至少有一個線程。

(2)資源分配給進程,同一進程的所有線程共享該進程的所有資源。

(3)處理機分給線程,即真正在處理機上運行的是線程。

(4)線程在執行過程中,需要協作同步。不同進程的線程間要利用消息通信的辦法實現同步。線程是指進程內的一個執行單元,也是進程內的可調度實體.

進程與線程的區別:

(1)調度:線程作爲調度和分配的基本單位,進程作爲擁有資源的基本單位

(2)併發性:不僅進程之間可以併發執行,同一個進程的多個線程之間也可併發執行

(3)擁有資源:進程是擁有資源的一個獨立單位,線程不擁有系統資源,但可以訪問隸屬於進程的資源.

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

線程/進程的執行特性。

線程只有 3 個基本狀態:就緒,執行,阻塞。

線程存在 5 種基本操作來切換線程的狀態:派生,阻塞,激活,調度,結束。

進程至少有 5 種基本狀態,它們是:初始態,執行態,等待狀態,就緒狀態,終止狀態。

進程間通信的方式:

(1)管道(pipe)及有名管道(named pipe)

(2)信號(signal)

(3)消息隊列(message queue)

(4)共享內存(shared memory)

(5)信號量(semaphore):主要作爲進程之間及同一種進程的不同線程之間得同步和互斥手段。

(6)套接字(socket):這是一種更爲一般得進程間通信機制,它可用於網絡中不同機器之間的進程間通信,應用非常廣泛。

線程可以有效地提高系統的執行效率,但並不是在所有計算機系統中都是適用的,如某些很少做進程調度和切換的實時系統。使用線程的好處是有多個任務需要處理機處理時,減少處理機的切換時間;而且,線程的創建和結束所需要的系統開銷也比進程的創建和結束要小得多。最適用使用線程的系統是多處理機系統和網絡系統或分佈式系統。

可能是感覺我計算機理論知識一般,然後轉向談一談IOS的問題

五、你對常用的蘋果設備的分辨率瞭解嗎?
答:我目前在開發中常接觸的就是iPhone 6 plus 分辨率:1080*1920; iPhone 6 :750*1334; iPhone 5s : 640*1136

當時覺得自己回答的沒錯,但後來發現是自己愚蠢了。 因爲蘋果設備所說的分辨率要分兩種:物理分辨率、邏輯分辨率。 4S之前這兩種分辨率是一種,但是之後就分開來說了。 物理分辨率就是我們通常所說的設備分辨率,是評價一個屏幕好壞的重要指標。而邏輯分辨率是和UI設計、屏幕適配相關聯的。 詳見下圖:
這裏寫圖片描述

六、那你說一下獲取iPhone手機分辨率的函數是哪個?

//獲取屏幕大小
var screenBounds:CGRect = UIScreen.mainScreen().bounds
println(screenBounds) // iphone6輸出:(0.0,0.0,375.0,667.0)

//獲取屏幕大小(不包括狀態欄高度)
viewBounds:CGRect = UIScreen.mainScreen().applicationFrame
println(viewBounds) //iphone6輸出:(0.0,20.0,375.0,647.0)

//但由於 UIScreen.mainScreen().applicationFrame 從 iOS9 起要被廢除,我們可以改用如下方法獲取不包括狀態欄高度的屏幕大小

//獲取屏幕大小(不包括狀態欄高度)
let viewBounds:CGRect = CGRectMake(0,20,UIScreen.mainScreen().bounds.width,UIScreen.mainScreen().bounds.height-20) //iphone6輸出:(0.0,20.0,375.0,647.0)

七、如何獲取當前設備屏幕是否爲高清屏

scale factor的值爲@1x是普通屏幕,物理分辨率320*480;iPhone4以前的設備。
@2x是視網膜屏,物理分辨率640*960 - 750*1334;iPhone4到iPhone6設備。
@3x是全高清屏,物理分辨率1080*1920;iPhone 6plus及以後設備。

判斷屏幕類型:
[plain]  
// 判斷屏幕類型,普通還是視網膜  
    float scale = [[UIScreen mainScreen] scale];  
    if (scale == 1) {  
        bIsRetina = NO;  
        NSLog(@"普通屏幕");  
    }else if (scale == 2) {  
        bIsRetina = YES;  
        NSLog(@"視網膜屏幕");  
    }else{  
        NSLog(@"全高清屏幕");  
    }  

八、TableView的樣式有哪兩個,分別是什麼,描述一下,區別有哪些?

答:UITableView有兩種樣式,一種是plain,一種是group。這兩種樣式,plain是普通樣式,group是分組樣式,plain更像是一個塊、一個分區,而group是一組一組。在外形上來說,plain是方形樣式,充斥着你給的view.frame座標。group是圓角樣式,跟iphone自帶的通訊錄編輯頁面類似。 plain的分組表頭懸停(也可以禁用懸停) group的分組表頭不懸停。

九、在TableView裏添加子TableView的函數名是什麼?

答:addSubview

以上這些是圖吧引擎組的電面所有問題,第一次電面,有點緊張,總體上感覺問的挺基礎,涉及的面很廣,校招這種招聘途徑還是很偏向考察理論基礎。 在今後還是要多花些時間在基礎知識,算法數據結構方面的學習,另外還要多看一些網上的面試技巧。 以上的問題如果有我總結的不對或不好的地方,歡迎各位朋友批評指正。

發佈了38 篇原創文章 · 獲贊 15 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章