某日二師兄參加XXX科技公司的C++工程師開發崗位第17面:
面試官:聊一聊指標?
二師兄:好的,
面試官:你覺得指標本質上是什么?
二師兄:這要從記憶體地址開始說起了,如果有一塊容量是1G的記憶體,假設它的地址是從
0x00000000到0x3fffffff,每一個位元組都對應一個地址,當我們宣告一個變數并初始化它時:
int a = 42;
二師兄:作業系統會分配一塊容量為
4(sizeof(int))的地址,這塊記憶體的首地址是0x00001000(假設),結束地址是0x00001003,在申請的這4個位元組上放入42,當我們對這個變數取地址時,
int a = 42;
int* p = &a;
二師兄:作業系統會再分配一塊記憶體,這塊記憶體的大小是
sizeof(int*),這塊記憶體的起始地址是0x00002000(假設),結束地址是0x00002003(32位作業系統),然后將&a取到的起始地址0x00001000放入0x00002000-0x00002003中,并將剛分配的這塊記憶體的起始地址賦給p,

二師兄:當我們對
p操作時,是對0x00002000-0x00002003這塊記憶體操作,當我們對*p(解參考)操作時,是對0x00001000-0x00001003這塊記憶體操作,二師兄:回到問題,我覺得指標的本質就是記憶體地址,雖然指標指向一塊記憶體地址,但它同時也是一個變數,也可以對指標取地址,如果對指標取地址,同樣可以得到一個記憶體地址(如
0x00002000),如果把這個記憶體地址存起來,那么指向這個記憶體地址的變數的型別就是二級指標(int**),面試官:好的,在
0x00002000-0x00002003這塊記憶體中,我們放入了一個地址是0x00001000,但是并沒有這個地址的長度,只知道一個地址而不知道長度,怎么能把資料取出來?二師兄:這主要是因為
p的型別是int*,當對p解參考時,編譯器知道了解參考的結果是int型別,所以從0x00001000往后讀取4個位元組(sizeof(int)),并按照當前CPU的模式(考慮大小端)把這四個位元組組成一個int型別的變數,面試官:
malloc函式你知道吧,回傳的型別是void*,在free的時候怎么知道這塊記憶體的大小的呢?二師兄:額,,這個還不太清楚,,
面試官:沒關系,今天就到這里,回去等通知吧,
讓我們來看看讓二師兄折戟的這個問題:
malloc函式回傳的型別是void*,在free的時候怎么知道這塊記憶體的大小的呢?
這里牽扯到malloc和free的實作方式,不同的廠商實作的方式不盡相同,以ptmalloc為例,當使用malloc申請size = 16的記憶體時,malloc會從記憶體池中分配一塊sizeof(chunk)+16長度的記憶體,chunk段保存了一些前后chunk的資訊,也保存了這塊記憶體的大小(16),malloc函式回傳的地址是0x00001000,而在free(0x00001000)時,free函式會用0x00001000減去特定值(sizeof(chunk)),得到chunk的起始地址,從chunk中獲取這塊記憶體真正的尺寸,從而完成free的任務,拋開記憶體的利用率不說,這是一個非常美妙的實作!

好了,今日份面試到這里就結束了,關注我,每天帶你學習一個C++小知識!
關注我,帶你21天“精通”C++!(狗頭)
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/555451.html
標籤:其他
上一篇:Java 注釋及Dos命令
下一篇:返回列表
