說明:所有題目均摘錄於網絡以及我所見過的面試題目,歡迎補充!
無特殊說明情況下,下面所有題s目都是linux下的32位C程序。
1、堆和棧有什么區別?
(1)棧由操作系統分配和釋放;堆則是程序員手動去申請釋放;
(2)棧是一塊連續的內存區域,也就是棧頂地址和棧的最大容量是系統規定的;堆是不連續的內存區域,是因為系統使用鏈表來存儲空閑內存地址。
(3)對於棧,在函數調用時,第一個入棧的是函數調用語句的下一條可執行語句的地址,然后是函數參數(一般是從右到左)入棧,最后是局部變量(靜態變量不入棧)。函數調用結束后,局部變量先出棧,然后是參數。對於堆,一般在堆頭部用一個字節存放堆大小,其他內容由程序員安排。
2、棧可能是向上生長,也可能是向下生長,試寫一段代碼,判斷棧生長方向?
解析:我們可以根據局部變量入棧的特性來判斷,由棧的連續性還有局部變量入棧的方式,我們可以來判斷棧的生長方向。
bool StackDownward() { int a = 1; int b = 2; if(&a > &b) { return true; } else { return false; } }
3、定義一個宏,來求結構體中某成員的偏移量
#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER )
解析:將0轉換為(TYPE *)類型,也就是結構體首地址為0,因此數據成員的偏移量也就是相對於0的偏移量,直接取該成員地址就是所求的偏移量。
4、判斷大小端
可用兩種方法,如下:
BOOL IsBigEndian() { int a = 0x1234; char b = *(char *)&a; //通過將int強制類型轉換成char單字節,通過判斷起始存儲位置。即等於取b等於a的低地址部分
if( b == 0x12) { return TRUE; } return FALSE; }
聯合體union的存放順序是所有成員都從低地址開始存放,利用該特性可以輕松地獲得了CPU對內存采用Little-endian還是Big-endian模式讀寫:
BOOL IsBigEndian() { union NUM { int a; char b; }num; num.a = 0x1234; if( num.b == 0x12 ) { return TRUE; } return FALSE; }
關於大小端的概念:
1) Little-Endian就是低位字節排放在內存的低地址端,高位字節排放在內存的高地址端。
2) Big-Endian就是高位字節排放在內存的低地址端,低位字節排放在內存的高地址端。
舉一個例子,比如數字0x12 34 56 78在內存中的表示形式為:
1)大端模式:
低地址 -----------------> 高地址
0x12 | 0x34 | 0x56 | 0x78
2)小端模式:
低地址 ------------------> 高地址
0x78 | 0x56 | 0x34 | 0x12
可見,大端模式和字符串的存儲模式類似。
參考:
1、《詳解大端模式和小端模式》https://blog.csdn.net/ce123_zhouwei/article/details/6971544