1. 程式人生 > >C/C++基礎筆試(一)

C/C++基礎筆試(一)

  面試時總會遇到一些基礎題目,其實也是大部分以往見過或者網上可以搜尋到的,都是十分基礎的問題,這類問題答對了不會給自己加多少分;但如果答錯或者答得不完整,自己在面試官眼裡就是基礎不牢固的印象。所以好記性不如爛筆頭,將遇到的部分筆試題,重新整理答案在部落格。

題目1: static 作用
答案:
對於C語言來說:
1)在函式體,一個被宣告為靜態的變數在這一函式被呼叫過程中維持其值不變。
2) 在模組內(但在函式體外),一個被宣告為靜態的變數可以被模組內所用函式訪問,但不能被模組外其它函式訪問。它是一個本地的全域性變數。
3) 在模組內,一個被宣告為靜態的函式只可被這一模組內的其它函式呼叫。那就是,這個函式被限制在宣告它的模組的本地範圍內使用。
對於C++語言來說:


在類中,static可以用來修飾靜態資料成員和靜態成員方法
靜態資料成員
(1)靜態資料成員可以實現多個物件之間的資料共享,它是類的所有物件的共享成員,它在記憶體中只佔一份空間,如果改變它的值,則各物件中這個資料成員的值都被改變。
(2)靜態資料成員是在程式開始執行時被分配空間,到程式結束之後才釋放,只要類中指定了靜態資料成員,即使不定義物件,也會為靜態資料成員分配空間。
(3)靜態資料成員可以被初始化,但是隻能在類體外進行初始化,若為對靜態資料成員賦初值,則編譯器會自動為其初始化為0 。
(4)靜態資料成員既可以通過物件名引用,也可以通過類名引用。
靜態成員函式
(1)靜態成員函式和靜態資料成員一樣,他們都屬於類的靜態成員,而不是物件成員。
(2)非靜態成員函式有this指標,而靜態成員函式沒有this指標。
(3)靜態成員函式主要用來方位靜態資料成員而不能訪問非靜態成員。

題目2:volatile關鍵字的作用,並舉例
答案:
作用:防止編譯對程式的優化
舉例:
  1)中斷服務程式中修改的供其它程式檢測的變數需要加volatile;
  2)多工環境下各任務間共享的變數應該加volatile;
  3)儲存器對映的硬體暫存器通常也要加volatile說明,因為每次對它的讀寫都可能有不同意義。

題目3:const和#define
答案:
1) 編譯器處理方式不同
 define巨集是在預處理階段展開。
 const常量是編譯執行階段使用。
2)型別和安全檢查不同
 define巨集沒有型別,不做任何型別檢查,僅僅是展開。
 const常量有具體的型別,在編譯階段會執行型別檢查。
3) 儲存方式不同
 define巨集僅僅是展開,給出的是立即數,不分配記憶體,在記憶體中會有多個拷貝,消耗記憶體大。
 const常量在靜態儲存區中分配空間,在程式執行過程中記憶體中只有一個拷貝。
4)空間和效率
在編譯時, 編譯器通常不為const常量分配儲存空間,而是將它們儲存在符號表中,這使得它成為一個編譯期間的常量,沒有了儲存與讀記憶體的操作,使得它的效率也很高。
巨集替換隻作替換,不做計算,不做表示式求解。
巨集定義的作用範圍僅限於當前檔案。
預設狀態下,const物件只在檔案內有效,當多個檔案中出現了同名的const變數時,等同於在不同檔案中分別定義了獨立的變數。 如果想在多個檔案之間共享const物件,必須在變數定義之前新增extern關鍵字(在宣告和定義時都要加)。

題目4:過載和覆蓋
答案:
過載(overload)
1)函式或者方法有相同的名稱,但是引數列表不相同(型別、順序、數目)的情形,這樣的同名不同引數的函式或者方法之間,互相稱之為過載函式或者方法
2) 僅是函式的返回值無法重灌,過載要求引數列表必須不同。
3) 程式是根據引數列表來確定具體要呼叫哪個函式的。

覆蓋(重寫override)
1)覆蓋是存在類中,子類重寫從基類繼承過來的函式。但是函式名、返回值、引數列表都必須和基類相同。
2)當子類的物件呼叫成員函式的時候,如果成員函式有被覆蓋則呼叫子類中覆蓋的版本,否則呼叫從基類繼承過來的函式
3) 如果子類覆蓋的是基類的虛擬函式,利用基類指標指向不同的子類物件,在執行的時候動態的決定要呼叫哪個子類虛擬函式,從而實現多型。

兩者區別:
1)過載要求函式名相同,但是引數列表必須不同,返回值可以相同也可以不同;
  覆蓋要求函式名、引數列表、返回值必須相同。
2)在類中過載是同一個類中不同成員函式之間的關係;
  在類中覆蓋則是子類和基類之間不同成員函式之間的關係。
3)過載函式的呼叫是根據引數列表來決定呼叫哪一個函式;
  覆蓋函式的呼叫是根據物件型別的不同決定呼叫哪一個。
4)在類中對成員函式過載是不能夠實現多型。

題目5:浮點型、整型、布林型數、指標與0比較
答案:
float:

float aif(a < 0.000001 && a > -0.000001)

int:

int i;
if(i == 0)
if(i != 0)

bool:

bool b;
if(b)
if(!b)

*p:

int *p;
if(p == NULL)
if(p != NULL)

題目6:程序和執行緒的區別
答案:
1)程序是cpu資源分配的最小單位,執行緒是cpu排程的最小單位。
2)程序有自己的獨立地址空間,每啟動一個程序,系統就會為它分配地址空間,建立資料表來維護程式碼段、堆疊段和資料段;執行緒共享程序的資源,一個程序至少有一個執行緒。
3)執行緒之間的通訊更方便,同一程序下的執行緒共享全域性變數、靜態變數等資料,而程序之間的通訊需要以通訊的方式(IPC)進行。不過如何處理好同步與互斥是編寫多執行緒程式的難點。
4)多程序程式更健壯,多執行緒程式只要有一個執行緒死掉,整個程序也死掉了;而一個程序死掉並不會對另外一個程序造成影響,因為程序有自己獨立的地址空間。
5)執行緒中執行時一般都要進行同步和互斥,因為他們共享同一程序的所有資源。
6)執行緒是輕兩級的程序,它的建立和銷燬所需要的時間比程序小很多,所有作業系統中的執行功能都是建立執行緒去完成的。

題目7:指標和引用
答案:
1)都是地址範疇;指標指向一塊記憶體,它的內容是所指記憶體的地址;引用是某塊記憶體的別名。
2)指標可以是空值,可以在任何時候被初始化;引用不可以為空,當被建立的時候,必須初始化。
3)指標可以用const修飾;引用不可以用const修飾。
4)指標可以有多級;引用只能是一級(int **p;合法 而 int &&a是不合法的)。
5)指標的值在初始化後可以改變,即指向其它的儲存單元;引用在進行初始化後就不能再改變。
6)”sizeof指標”得到的是指標本身的大小;”sizeof引用”得到的是所指向的變數(物件)的大小。
7)指標和地址運用自增(++)不同,指標是地址進行自增;引用是值進行自增。
8)如果返回動態記憶體分配的物件或者記憶體,必須使用指標,返回引用可能引起記憶體洩漏。

題目8:判斷CPU模式,小端模式返回0,大端模式返回1
答案:
首先知道大、小端模式;
大端模式:資料的高位元組儲存在記憶體的低地址中,而資料的低位元組儲存在記憶體的高地址中,這樣的儲存模式有點兒類似於把資料當作字串順序處理:地址由小向大增加,而資料從高位往低位放;這和我們的閱讀習慣一致。網路資料一般為大端模式。
小端模式:資料的高位元組儲存在記憶體的高地址中,而資料的低位元組儲存在記憶體的低地址中,這種儲存模式將地址的高低和資料位權有效地結合起來,高地址部分權值高,低地址部分權值低。
程式碼:用聯合體方式判斷

int check(void)
{
    union x
    {
        int a;
        char b;
    }c;
    c.a = 1;
    return(c.b != 1);
}

題目9:寫一個”標準”巨集MIN ,這個巨集輸入兩個引數並返回較小的一個

答案:

#define MIN(A,B) ((A) <= (B) ? (A) : (B))