1. 程式人生 > >記一次阿裏電面經歷

記一次阿裏電面經歷

art 存儲空間 自由 結束 eas 大型 特定 easy col

昨天下午(3/19)三點多鐘,接到了一個杭州的電話,是阿裏的。問我是否方便聊聊。我說我在上課,四點下課。然後他就四點多鐘的時候又打了一次過來。

項目經歷

上來就問我有無大型項目的經歷。不好意思,我說無。。

。又問我代碼量怎樣,我說之前有常常刷ACM的題目,所以代碼量還能夠。

C語言變量

問:“函數中的局部變量保存在哪裏?”

答:“棧”

問:“函數中的局部靜態變量保存在哪裏?”

答:“靜態區。。”

問:“局部靜態變量和全局靜態變量有不同嗎,不同點在哪裏?”

答:“。

。沒太大不同,都存在一起。。”

問:“不是問的存儲位置。其它方面呢?”

答:“哦,可視的範圍不同。全局靜態變量全局可見。局部靜態變量僅僅有函數內部可見。”

問:“全局變量和全局靜態變量有何不同”

答:“存的位置是挨著的。要說不同的話,也是可視範圍吧,全局靜態變量僅在當前文件內可見,全局變量是該項目全部文件可見。

聯合(union)

問:“知道聯合嗎?”

答:“union”

問:“和結構體有何不同?”

答:“聯合的每一個成員的擁有共同的起始地址(共享存儲空間)。而結構體為每一個成員單獨分配空間。

問:“union這樣設計的目的是什麽(union有何用途)?”

以下我就趕快頭腦風暴了一下。。

絞盡腦汁地的表達自己的拙見。該部分內容你能夠無視,我認為自己扯得也有點遠。。

“這樣設計節省內存空間。有時候在某個特定的情況下。我們僅僅須要用的某種特定的類型,怎樣像結構體那樣則浪費了存儲空間。在曾經的時候Linux編程(POSIX)中IP地址的結構體(struct in_addr)就是一個聯合(也可能是結構體成員是聯合),比方成員是4個元素char數組,兩個元素的short數組,或一個int等等,這樣我們就能根據不同的網絡類型(A類、B類、C類)來自由的獲取該地址的網絡號或主機號(比方。要獲得一個網絡的網絡號。若是一個A類地址,我們就讀取char數組第一個元素。B類地址我們就讀取short的第一個元素來)”

當然了如今的struct in_addr 裏面實際上僅僅是包括一個整型的結構體了。

不是聯合了。上面關於in_addr和聯合的說法是從《UNP》上看來的。

算法

大數相加的算法

問:“怎樣實現兩個數的相加(超過了long long這些的範圍了)?”

答:“用一個字符數組來存儲數字,然後依次遍歷每一個字符。通過減‘0’字符的方法轉換為數字。再逐位相加。。

這是比較經典的大數算法。

但他事實上沒等我說完就打斷我了

問:“這樣當然能夠,可是這樣的方法效率非常低。有沒有高效的方法”

答:“不會了”

問:“再想半分鐘”

答:“真的不會了(對自己也是無語。求網友告知算法)”

其它算法

問:“你還了解哪些算法”

答:“大部分是學數據結構涉及到的算法,BFS,DFS,最小生成樹。最短路徑等等。hash也算一種算法吧,還有排序算法。其它的比方像並查集這樣的數據結構也算吧。”

關於算法我沒敢多提,由於我也怕他深入地問下去,好久沒搞算法了,這次沒準備,肯定會跪。

只是他也沒深入的問下去

書籍

問:“你沒有項目經驗。那你讀過什麽經典書籍嗎?”

答:“C++ primer,Think in C++也讀過一點。(事實上讀過一點的經典書籍還有非常多。。

)”

const指針

問:“聲明一個常量指針,指向一個整型。但指向的地址不可變”

哎,這個我知道是重點,也是easy混淆的知識點。前幾天我還特地整理了一下。只是,給我點時間我自己慢慢梳理一下能夠答好的。他這一問,我才發現我還是掌握不堅固。

答錯了。他又指導了我一下。

正確的答案是:const int * a(int const * a)。

int * const a 是指向的整型的值不可變,指針本身可變。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

總結一下,速記方法:關鍵的是const與星號(*)的位置。int永遠在星號左邊的。記成“反轉”即可了。

能夠忽略到int。

那麽就僅僅有兩種形式

const * a和* const a。表面上const * a const在星號前面應該是修飾指針的,可是要反轉記憶一下,它是修飾變量的。

即變量是常量。

* const a表面上,cosnt在a前面應該是修飾變量的,實際上它是修飾指針的,即地址是常量不能變。


以上僅僅是速記的方法。並非C語言設計者的設計意圖。

。。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

內存對齊

問:“比方你malloc了一段內存,它的地址不是內存對齊的,怎樣實現8字節的內存對齊?”

答:“一個預處理的那個#pragma能夠實現(#pragma pack(8))”

問:“這是用編譯器來實現。有沒有軟件方式?”

接下來是在他的提示下,我大概推測了一下回答的。

答:“先推斷malloc的內存地址是不是內存對齊的”

問:“怎樣推斷?”

答:“8字節對齊。那麽內存地址應該是8的倍數,能夠%8(對8求余)”

問:“這會涉及到除法運算,效率比較低。”

答:“那就用位操作,能夠按位與,前面幾位是0後面三位是1,哦,我說的是二進制(十進制7)。

然後推斷值是否為0”

問:“假設結果是沒有對齊,該怎樣對齊呢?”

接下來就全然是我的臆測了

答:“那就給這個地址指針加一下。差多少就加多少,可能還要根據指針類型進行一些轉換。

”(答的不好。只是他也沒提反對意見,就下一題了


--------------------------------------------------------------------------------------------------------------------------------------------------------------

後來我自己手動敲了一下代碼。須要註意的問題是指針是不能直接進行求余或位操作的,進行指針到int類型的強制類型轉換是失敗的。

可選方案例如以下:

假設是C++的話。使用reinterpret_cast

long pp = reinterpret_cast<long>(p); // p 是char *類型

假設pp是int型(reinterpret<int>(p))則會報錯提示丟失精度(gcc 64位)。

二面的時候面試官又問了相同的問題,只是問的細節很多其它,他說能夠用static_cast<>來轉換指針為整型。

我後來試了一下發現不能夠。。會報錯的。所以我嘗試了reinterpret_cast<>

假設是C++的話。就:

int pp = reinterpret_cast<int>(p); // p是char *類型

C語言盡管沒這個功能,但事實上要想比較指針地址是否是8的倍數,實現還是比較簡單的,指針類型是無法指針做&操作的。

可是我們能夠進行一個小轉換:

//a 是malloc的返回值。char *類型
if ((a - (char *)0) & 7)
{
....
}

當然這段代碼C++也能夠用。

要註意的是malloc的返回值最好要強制類型轉換為 char *:

// 比方分配一百的個字符的空間。
char *p = (char *)malloc(sizeof(char)*(100+8)); // 多分配8個字節的空間。為了以後的偏移留足空間。

盡管理論上malloc的返回值能夠轉化為隨意指針類型比方:int *。

可是要註意到指針的加減操作。所偏移的單位是指向類型的大小。比方:

// 假設p是int *類型
p += 1; // p向後偏移1*4個字節(int是4個字節)
// 假設p是char *類型
p += 1; // p向後偏移1*1個字節(char是1個字節)

非常明顯char *類型的指針偏移的準確度更高。這也是為什麽我們通常把malloc返回值轉換為char *而不是int *的原因。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

回調函數

問:“C++中怎樣實現回調函數”

回調函數,挺熟的名字,callback。

。。可是詳細是個什麽意思還真不好說。記得在安卓裏面見到過。就扯了一下安卓。

問:“那麽在C++中該怎樣實現呢”

接下來。確實也是運氣。

腦袋裏冒出個函數指針,就脫口而出了。說了個一般的函數指針使用方法。貌似說對了。

答:“函數指針吧,先什麽一種類型的函數的函數指針,然後你能夠自己去實現這樣的類型的函數。然後再把這個函數作為參數傳遞給函數中(參數是函數指針的函數)。

內存分配原理

問:“有沒有看過內存分配管理的源代碼?比方malloc之類的。

答:“沒有啊。那大概是匯編吧”(記得大概是Linus說過早期的malloc是用匯編實現的。如今就不知道了。

。)

問:“也不是涉及詳細語言,就是內存管理的算法了解嗎?”

答:“沒看過這方面的不了解。。”

然後問題就結束了。如今想想他的意思大概是要我從操作系統的知識方面談一下內存管理的算法,比方掃描一下,哪裏未使用的空間就分配出去之類的。


後來問我有什麽問題。

我基本沒啥問題。問了點弱智問題。

問:“是內推的你們會打電話過來(在某群裏找了個內推。

)還是全部在官方申請實習的。你們都會打電話過來?”

答:“一般全部申請的都我們會打過去。


---------

後來第二天打來第二個電話。二面。。只是二面掛了。。

記一次阿裏電面經歷