C 面試問題

2021-10-07 06:53:29 字數 4149 閱讀 9914

1、概念

陣列:儲存連續多個相同型別的資料;

2、賦值

同型別的指標變數可以相互賦值,陣列不行,只能乙個乙個元素的賦值或拷貝

3、儲存方式

陣列:連續記憶體空間。

4、sizeof

陣列的sizeof求的是占用的空間(位元組)。

在32位平台下,無論指標的型別是什麼,sizeof(指標名)都是4,在64位平台下,無論指標的型別是什麼,sizeof(指標名)都是8。

5、傳參

作為引數時,陣列名退化為常量指標

1、指標陣列:就是陣列,元素是指標;

2、陣列指標:就是指標,指向乙個陣列;

1.指標函式 type *function(int, int)

type *function(int, int)與普通函式int function(int,int)類似,只是返回的資料型別不一樣而已,type *function(int, int)返回的是指標位址,int function(int,int)返回的是int型資料。

2.函式指標__type__ (*function)(int,int)

type(*function)(int,int)只是乙個指標,變數指標是指向乙個變數的位址,結構體指標是指向乙個結構體的首位址,而函式指標是指向乙個函式的位址,它是一種型別,比int,char高階的型別。

1.指標和引用的定義和性質區別:

int a=1;int *p=&a;

int a=1;int &b=a;

上面定義了乙個整形變數和乙個指標變數p,該指標變數指向a的儲存單元,即p的值是a儲存單元的位址。

而下面2句定義了乙個整形變數a和這個整形a的引用b,事實上a和b是同乙個東西,在記憶體占有同乙個儲存單元。

(2)可以有const指標,但是沒有const引用;

(3)指標可以有多級,但是引用只能是一級(int **p;合法 而 int &&a是不合法的)

(4)指標的值可以為空,但是引用的值不能為null,並且引用在定義的時候必須初始化;

(5)指標的值在初始化後可以改變,即指向其它的儲存單元,而引用在進行初始化後就不會再改變了。

(6)"sizeof引用"得到的是所指向的變數(物件)的大小,而"sizeof指標"得到的是指標本身的大小;

(7)指標和引用的自增(++)運算意義不一樣;

1、相對於c中struct,c++做了很大的擴充。基本上和class 差不多。只有一些細節上的差別。

2、對於成員的預設訪問許可權,class是private,struct是public。需要注意的是,程式中應該明確指出訪問許可權,不要依賴預設的訪問許可權。對於其它預設的情況也是一樣,盡量明確指出來,這是乙個良好的程式設計習慣,增加**的可讀性。

3、對於預設的繼承方式,class是private,struct是public。需要注意的是,class可繼承class,也可繼承struct。struct可繼承struct,也可繼承class。預設的繼承方式取決於子類是struct還是class。和上面一樣,這裡應該明確指出繼承方式,而不應該依賴預設。

4、對於struct和class,都可以使用使用{}來賦初值,前提是:a、欄位是public,因為public才可以直接訪問;b、沒有父類,沒有自定義構造方法和虛方法,可以有普通的成員方法。可以認為,繼承,自定義構造方法,虛方法改變了類的內部結構,因此編譯器禁止使用{}賦初值。

5、定義模版引數,使用typename,也可以使用class。但是不能使用struct。

1)管理方式:堆中資源由程式設計師控制(通過malloc/free、new/delete,容易產生memory leak),棧資源由編譯器自動管理。

(2)系統響應:對於堆,系統有乙個記錄空閒記憶體位址的鍊錶,當系統收到程式申請時,遍歷該鍊錶,尋找第乙個大於所申請空間的空間的堆結點,刪除空閒結點鍊錶中的該結點,並將該結點空間分配給程式(大多數系統會在這塊記憶體空間首位址記錄本次分配的大小,這樣delete才能正確釋放本記憶體空間,另外,系統會將多餘的部分重新放入空閒鍊錶中)。對於棧,只要棧的剩餘空間大於所申請空間,系統就會為程式分配記憶體,否則報異常出現棧空間溢位錯誤。

(3)空間大小:堆是不連續的記憶體區域(因為系統是用鍊錶來儲存空閒記憶體位址的,自然不是連續),堆的大小受限於計算機系統中有效的虛擬記憶體(32位機器上理論上是4g大小),所以堆的空間比較靈活,比較大。棧是一塊連續的記憶體區域,大小是作業系統預定好的,windows下棧大小是2m(也有是1m,在編譯時確定,vc中可設定)。

(4)碎片問題:對於堆,頻繁的new/delete會造成大量記憶體碎片,降低程式效率。對於棧,它是乙個先進後出(first-in-last-out)的結構,進出一一對應,不會產生碎片。

(5)生長方向:堆向上,向高位址方向增長;棧向下,向低位址方向增長。

(6)分配方式:堆是動態分配(沒有靜態分配的堆)。棧有靜態分配和動態分配,靜態分配由編譯器完成(如函式區域性變數),動態分配由alloca函式分配,但棧的動態分配資源由編譯器自動釋放,無需程式設計師實現。

(7)分配效率:堆由c/c++函式庫提供,機制很複雜,因此堆的效率比棧低很多。棧是機器系統提供的資料結構,計算機在底層對棧提供支援,分配專門的暫存器存放棧位址,提供棧操作專門的指令。

malloc與free是c++/c語言的標準庫函式,new/delete是c++的運算子。它們都可用於申請動態記憶體和釋放記憶體。對於非內部資料型別的物件而言,光用maloc/free無法滿足動態物件的要求。物件在建立的同時要自動執行建構函式,物件在消亡之前要自動執行析構函式。由於malloc/free是庫函式而不是運算子,不在編譯器控制許可權之內,不能夠把執行建構函式和析構函式的任務強加於malloc/free。因此c++語言需要乙個能完成動態記憶體分配和初始化工作的運算子new,以乙個能完成清理與釋放記憶體工作的運算子delete。

malloc是c語言的庫函式,其作用是在記憶體中開闢一塊連續的指定大小的記憶體空間(注意:呼叫malloc必須要指定開闢的空間大小),返回指向該被分配記憶體的指標(該指標為void * ,需要通過強制型別轉換將void*指標轉換成我們需要的型別)。

//用例

int* ptr =

(int

*) malloc (

sizeof

(int))

//分配乙個int型別大小的空間

float

* ptr2 =

(float

*) malloc (

sizeof

(int))

//分配float型別大小空間

一般情況下 malloc總是能成功分配一塊連續的記憶體空間,但當記憶體耗盡或者記憶體過於碎片化而不足以開闢固定大小的連續空間的時候,malloc則呼叫失敗,這時候malloc會返回乙個空指標null,所以每次使用malloc時以防萬一都應該先判斷其返回指標是否為空防止。

new是c++提供的乙個操縱符(或者說關鍵字)。其也是用於分配記憶體的。其呼叫過程可以分解為三個步驟:

1、呼叫operator new(可過載函式)分配記憶體

2、在所分配的記憶體中呼叫物件的建構函式,構造物件

3、返回指向該記憶體空間的指標

值得一提的是,new內部開闢記憶體空間的原理也是呼叫malloc函式,其呼叫過程被封裝在operator new內部,可以說new是在malloc的基礎上再封裝了一系列功能。與malloc有所區別的是,new在operator new開闢出空間後,會呼叫物件的建構函式在該空間中構造物件最後返回物件,而malloc只負責開闢空間,並不負責構造物件;並且new 在分配空間失敗後並不是返回空指標而是丟擲乙個 std::bad_alloc 異常。

delete與free:

free與delete的作用與上面提到的new和delete相反。free函式只需傳入指向某一塊已分配記憶體的指標,便能自動釋放掉這些記憶體。而為何呼叫malloc需要傳入開闢空間大小而free不用傳入需要釋放的空間大小呢?其實原因在於malloc分配空間的時候,不僅會按照傳入引數大小分配空間大小,還會在該段記憶體頭部和尾部插入一些額外的資訊(俗稱cookie),其中包含了記憶體大小的資訊。這樣free函式只需要讀取該資訊,便可以知道要釋放的記憶體大小、範圍等。

而delete呼叫過程則與new相反,其呼叫過程也同樣可以分解:

1、呼叫物件的析構函式

2、呼叫operator delete

delete與new 相對應,其釋放記憶體空間的原理也是呼叫free函式,其呼叫過程被封裝在operator delete內部,即delete是在free的基礎上封裝了一系列功能。delete首先呼叫物件的析構函式,然後底層呼叫free釋放該區域記憶體。

面試問題c

1 如何避免記憶體洩漏 2 namespace 3 如何防止記憶體洩漏 4 堆和棧的區別 5 記憶體的幾種形式 6 linux指令 1 如何避免記憶體洩漏 答 記憶體洩漏 記憶體洩漏是指由於未能釋放掉不再使用的記憶體情況,並不是指內存在物理上的消失,而是應用程式分配某段記憶體後,由於設計錯誤失去了對...

C 面試問題

一面 1 多型性都有哪些?靜態和動態,然後分別敘述了一下虛函式和函式過載 2 動態繫結怎麼實現?就是問了一下基類與派生類指標和引用的轉換問題 3 型別轉換有哪些?四種型別轉換,分別舉例說明 4 操作符過載 操作符 具體如何去定義,讓把操作符過載函式原型說一遍 5 記憶體對齊的原則?原則敘述了一下並舉...

C 面試問題

一面 1 多型性都有哪些?靜態和動態,然後分別敘述了一下虛函式和函式過載 2 動態繫結怎麼實現?就是問了一下基類與派生類指標和引用的轉換問題 3 型別轉換有哪些?四種型別轉換,分別舉例說明 4 操作符過載 操作符 具體如何去定義,讓把操作符過載函式原型說一遍 5 記憶體對齊的原則?原則敘述了一下並舉...