您現在的位置是:首頁 > 手機遊戲首頁手機遊戲

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

簡介所以在實際的C語言程式開發中,為了避免出現“懸空指標”引發不可預知的錯誤,在釋放記憶體之後,常常會將指標 p 賦值為 NULL:void *p = malloc(size)

懸空指標和野指標是什麼csdn

早期的 Unix 作業系統主要是使用匯編編寫的,Dennis Ritchie 覺得很不方便,於是便於 1969 到 1973 年間,在貝爾實驗室開發了C語言。

C語言是一門面向結構化的高階程式語言(也有人認為它是中級語言),用於通用程式設計需求。基本上,C語言是其基本語法和庫函式的集合,因此程式設計師定義自己的函式並且將其包含在C語言庫中也是很方便的。

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

C語言的主要用途是編寫其他程式語言的編譯器、作業系統、文字編輯器、後臺服務程式、驅動程式、資料庫、指令碼語言的直譯器,以及其他各種實用的程式。

C語言甚至能夠編寫自己的編譯器。

如果讀者對C語言感興趣,並且希望得到一份C語言程式設計師的工作,那麼下面這 7 道面試題將會非常有趣。

問題1,C語言的顯著特點是什麼?

可移植。C語言是一種與平臺無關的程式語言,不使用平臺依賴庫的C語言程式可以輕易移植到各種平臺。模組化。我們能夠輕易的將一個非常大的C語言專案拆分成若干個小的模組,並逐個實現,最終組合解決該大專案。靈活。C語言給與程式設計師最大的自由,因此只要某種程式碼C語言的語法沒有禁止,程式設計師就可使用。也即所謂的“法無禁止即可行”。

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

問題2,什麼是C語言中的“懸空指標”?

C語言中的指標可以指向一塊記憶體,如果這塊記憶體稍後被作業系統回收(被釋放),但是指標仍然指向這塊記憶體,那麼,此時該指標就是“懸空指標”。下面這段C語言程式碼是一個例子,請看:

void *p = malloc(size);

assert(p);

free(p); // 現在 p 是“懸空指標”

C語言中的“懸空指標”會引發不可預知的錯誤,而且這種錯誤一旦發生,很難定位。這是因為在 free(p) 之後,p 指標仍然指向之前分配的記憶體,如果這塊記憶體暫時可以被程式訪問並且不會造成衝突,那麼之後使用 p 並不會引發錯誤。

最難除錯的 bug 總是不能輕易復現的 bug,對不?

所以在實際的C語言程式開發中,為了避免出現“懸空指標”引發不可預知的錯誤,在釋放記憶體之後,常常會將指標 p 賦值為 NULL:

void *p = malloc(size);

assert(p);

free(p);

// 避免“懸空指標”

p = NULL;

這麼做的好處是一旦再次使用被釋放的指標 p,就會立刻引發“段錯誤”,程式設計師也就能立刻知道應該修改C語言程式碼了。

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

C語言中的“野指標”是什麼?

問題3,C語言中的“野指標”是什麼?

“懸空指標”是指向被釋放記憶體的指標,“野指標”則是不確定其具體指向的指標。“野指標”最常來自於未初始化的指標,例如下面這段C語言程式碼:

void *p;// 此時 p 是“野指標”

因為“野指標”可能指向任意記憶體段,因此它可能會損壞正常的資料,也有可能引發其他未知錯誤,所以C語言中的“野指標”危害性甚至比“懸空指標”還要嚴重。在實際的C語言程式開發中,定義指標時,一般都要儘量避免“野指標”的出現(賦初值):

void *p = NULL;

void *data = malloc(size);

問題4,C語言中的 static 函式有什麼用?

相信讀者在不少的C語言專案中看到類似於下面這樣的 static 函式,為什麼使用 static 關鍵字修飾函式呢?這麼做有什麼用呢?

static void foo(){ 。。。}

稍大的C語言專案中一般都會出現這樣的 static 函式(靜態函式),C語言中的靜態函式最主要的特點就在於其作用域——僅限所述檔案。例如在 fun。c 檔案中定義的 static 函式,不能在如 main。c 等其他檔案中使用。

讀者可以嘗試使用 extern 關鍵字引入其他檔案中定義的 static 函式。

C語言中 static 函式的這個特性使得它常常被定義在 。h 檔案中,一般和 inline 關鍵字一起使用,以獲得 define 函式式宏定義類似的高效率。

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

C語言中的“迴圈”資料型別是指什麼?

問題5,C語言中的“迴圈”資料型別是指什麼?

所謂的“迴圈”資料型別,其實就是某種型別的資料溢位後,又從頭開始儲存。一個典型的例子是 unsigned char 變數若已經等於 255,仍然對其加 1,那麼該變數就會溢位從頭開始,也即等於零:

unsigned char a = 255;

a = a+1;// a 等於 0

unsigned char 型變數 a 是無符號的 8 位整數,它能表示的最大值是 8 個位全為 1,也即 0xff=255,若此時再對其加一,將得到 0x100。a 只索引 8 位,也即 0x100 中的 0x00=0。

C語言中的 int,long,short 等型別也有類似的“迴圈”特性,該特性不會引發語法編譯錯誤,因此較難判斷這些型別的變數是否溢位。而C語言中的 float,double 型別則沒有“迴圈”特性,因此實際C語言程式開發中一個常用的檢查整型資料是否溢位的技巧,就是藉助於 float 和 double 型別的,這一點在我之前的文章中說過,感興趣的讀者可以看看。

問題6,C語言中的標頭檔案有什麼用?

一般C語言程式專案中的標頭檔案字尾名都為 。h,h 是 header 的縮寫。標頭檔案的使用一般和 #include 結合使用,例如在 main。c 檔案中寫下:

#include “header。h”

意味著在該處將 header。h 中的內容展開到此。所以C語言中的標頭檔案中一般包含程式需要使用的函式定義和原型,也可以包含相關的資料結構型別定義。

這裡再囉嗦下“在該處將 header。h 中的內容展開到此”的含義——假如 header。h 標頭檔案中的內容是:

// header。h 標頭檔案

printf(“hello world\n”);

那麼,在其他檔案中寫下

#include “header。h”就等價於

// header。h 標頭檔案

printf(“hello world\n”);

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

C語言中的指標可以做加法運算嗎?

問題7,C語言中的指標可以做加法運算嗎?

C語言中的指標包含地址詳細資訊,一般是不可以直接做加法運算的,例如下面這段C語言程式碼:

void *p1 = (void *)1;

void *p2 = (void *)2;

// 下面是非法的

void *p = p1+p2;

讀者可自行嘗試,指標 p1 和指標 p2 是無法直接相加的,否則編譯器就會報錯。但是如果想對指標 p1 和 p2 的地址值相加,可以將其強制轉換為整數型別,例如:

void *p1 = (void *)1;

void *p2 = (void *)2;

long p = (long)p1 + (long)p2;

應該確保強制轉換的整數型別寬度大於指標型別寬度,否則可能會因為數值截斷導致得到錯誤的結果。

雖然C語言中的指標不能直接與指標相加,但是卻可以與其他整數相加,例如下面這段C語言程式碼:

char *p1 = (char *)1;

char *p = p1+1;

指標p1 指向地址 1,因此指標 p 指向地址 2,這沒什麼好說的。但是,讀者應該注意下面這樣的“陷阱”:

int *p1 = (int *)1;

int *p = p1+1;

與上面的C語言程式碼例子相比,這裡僅僅將 char 換成 int。那麼,指標 p 指向哪個地址呢?編寫列印程式碼:

int *p1 = (int *)1;

int *p = p1+1;

printf(“p1=%p, p=%p\n”, p1, p);

編譯並執行上面這段C語言程式碼,會發現輸出如下:

p1=0x1, p=0x5

可見,“1+1”並不等於 2,而是等於 5 了。這其實是因為C語言中的指標是有其自己的含義的,不同的指標型別索引記憶體的大小也往往不同,我的機器上 int 型別佔用 4 個位元組記憶體空間,因此指標 p1+1 實際上是往後移動了 4 個位元組。

讀者可自行將 int 換成其他型別試試。

更詳細的解釋可以參考我之前的文章,都已經分析的非常明白了。

小結

本節列舉的 7 個C語言問題其實屬於C語言的基本語法和特點,如果能夠熟練掌握,相信對找到一份相關的工作是有幫助的。

最常見,也最基本的7道C語言面試題,還是有不少人弄不明白

點個關注吧

歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。

未經許可,禁止轉載。

Top