c++筆試題3
一、【阿里C++面試題】
1、如何初始化一個指標陣列。
答案:
錯題解析:首先明確一個概念,就是指向陣列的指標,和存放指標的陣列。 指向陣列的指標:char (*array)[5];含義是一個指向存放5個字元的陣列的指標。 存放指標的陣列:char *array[5];含義是一個數組中存放了5個指向字元型資料的指標。 按照題意,我理解為初始化一個存放指標的陣列,char *array[2]={“China”,”Beijing”};其含義是初始化了一個有兩個指向字元型資料的指標的陣列,這兩個指標分別指向字串”China”和”Beijing”。
2、關鍵字const是什麼含意?
正確答案:
錯題解析:我只要一聽到被面試者說:“const意味著常數”,我就知道我正在和一個業餘者打交道。去年Dan Saks已經在他的文章裡完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什麼和不能做什麼.如果你從沒有讀到那篇文章,只要能說出const意味著“只讀”就可 以了。儘管這個答案不是完全的答案,但我接受它作為一個正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)如果應試者能正確回答這 個問題,我將問他一個附加的問題:下面的宣告都是什麼意思?
const int a;
int const a;
const int *a;
int * const a;
int const * a const;
前兩個的作用是一樣,a是一個常整型數。第三個意味著a是一個指向常整型數的指標(也就是,整型數是不可修改的,但指標可以)。第四個意思a是一個指向整 型數的常指標(也就是說,指標指向的整型數是可以修改的,但指標是不可修改的)。最後一個意味著a是一個指向常整型數的常指標(也就是說,指標指向的整型 數是不可修改的,同時指標也是不可修改的)。如果應試者能正確回答這些問題,那麼他就給我留下了一個好印象。順帶提一句,也許你可能會問,即使不用關鍵字 const,也還是能很容易寫出功能正確的程式,那麼我為什麼還要如此看重關鍵字const呢?我也如下的幾下理由: 1). 關鍵字const的作用是為給讀你程式碼的人傳達非常有用的資訊,實際上,宣告一個引數為常量是為了告訴了使用者這個引數的應用目的。如果你曾花很多時間清理 其它人留下的垃圾,你就會很快學會感謝這點多餘的資訊。(當然,懂得用const的程式設計師很少會留下的垃圾讓別人來清理的。) 2). 通過給優化器一些附加的資訊,使用關鍵字const也許能產生更緊湊的程式碼。 3). 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的引數,防止其被無意的程式碼修改。簡而言之,這樣可以減少bug的出現。
3、 什麼是動態特性?
正確答案:
錯題解析:在絕大多數情況下, 程式的功能是在編譯的時候就確定下來的, 我們稱之為靜態特性。 反之, 如果程式的功能是在執行時刻才能確定下來的, 則稱之為動態特性。C++中, 虛擬函式,抽象基類, 動態繫結和多型構成了出色的動態特性。
4、基類的有1個虛擬函式,子類還需要申明為virtual嗎?為什麼。
正確答案:
錯題解析:不申明沒有關係的。 不過,我總是喜歡顯式申明,使得程式碼更加清晰。
5、在C++ 程式中呼叫被 C 編譯器編譯後的函式,為什麼要加 extern “C”宣告?
正確答案:
錯題解析:函式和變數被C++編譯後在符號庫中的名字與C語言的不同,被extern “C”修飾的變數和函式是按照C語言方式編譯和連線的。由於編譯後的名字不同,C++程式不能直接呼叫C 函式。C++提供了一個C 連線交換指定符號extern“C”來解決這個問題。
6、如何定義Bool變數的TRUE和FALSE的值。
正確答案:
錯題解析:不知道這個題有什麼陷阱,寫到現在神經已經大了,一般來說先要把TURE和FALSE給定義了,使用#define就可以: #define TURE 1 #define FALSE 0 如果有一個變數需要定義成bool型的,舉個例子:bool a=TURE;就可以了。
7、行內函數INline和巨集定義一起使用的區別。
正確答案:
錯題解析:行內函數是在編譯的時候已經做好將對應的函式程式碼替換嵌入到對應的位置,適用於程式碼較少的函式。 巨集定義是簡單的替換變數,如果定義的是有引數的函式形式,引數不做型別校驗。
8、編寫my_strcpy函式,實現與庫函式strcpy類似的功能,不能使用任何庫函式;
正確答案:
char *strcpy(char *strDest, const char *strSrc)
{
if ( strDest == NULL || strSrc == NULL)
return NULL ;
if ( strDest == strSrc)
returnstrDest ;
char *tempptr = strDest ;
while( (*strDest++ = *strSrc++) != ‘’);
returntempptr ;
}
9、 完成程式,實現對陣列的降序排序
#include
void sort(int array[] );
int main()
{
int array[]={45,56,76,234,1,34,23,2,3}; //數字任//意給出
sort( array );
return 0;
}
void sort( int array[] )
{____________________________________
inti,j,k;
for(i=1;i<=7;i++) { if(array[i]>array[i-1])
{
k=ARRAY[i];
j=i-1;
do
{
array[j+1]=array[j];
j– ;
}
while(k>array[j]&&j>=0);
array[j+1]=k;
}
}
—————————————————–
}
10、ICMP是什麼協議,處於哪一層?
正確答案:
Internet控制報文協議,處於網路層(IP層)
11、 C中static有什麼作用
正確答案:
(1)隱藏。 當我們同時編譯多個檔案時,所有未加static字首的全域性變數和函式都具有全域性可見性,故使用static在不同的檔案中定義同名函式和同名變數,而不必擔心命名衝突。
(2)static的第二個作用是保持變數內容的持久。儲存在靜態資料區的變數會在程式剛開始執行時就完成初始化,也是唯一的一次初始化。共有兩種變數儲存在靜態儲存區:全域性變數和static變數。
(3)static的第三個作用是預設初始化為0.其實全域性變數也具備這一屬性,因為全域性變數也儲存在靜態資料區。在靜態資料區,記憶體中所有的位元組預設值都是0×00,某些時候這一特點可以減少程式設計師的工作量。
12、
Void GetMemory2(char **p, int num)
{
*p = (char *)malloc(num);
}
void Test(void)
{
char *str = NULL;
GetMemory(&str, 100);
strcpy(str, "hello");
printf(str);
}
請問執行Test函式會有什麼樣的結果?
正確答案:
可以執行
13、C++特點是什麼,如何實現多型?畫出基類和子類在記憶體中的相互關係。
正確答案:
多型的基礎是繼承,需要虛擬函式的支援,簡單的多型是很簡單的。 子類繼承父類大部分的資源,不能繼承的有建構函式,解構函式,拷貝建構函式,operator=函式,友元函式等等
14、 C++中的什麼是多型性? 是如何實現的?
正確答案:
多型性是面向物件程式設計語言繼資料抽象和繼承之後的第三個基本特徵。它是在執行時出現的多型性通過派生類和虛擬函式實現。基類和派生類中使用同樣的函式名, 完成不同的操作具體實現相隔離的另一類介面,即把" w h a t"從"h o w"分離開來。多型性提高了程式碼的組織性和可讀性,虛擬函式則根據型別的不同來進行不同的隔離。
15、 關鍵字static的作用是什麼?
正確答案:
這個簡單的問題很少有人能回答完全。在C語言中,關鍵字static有三個明顯的作用:
1). 在函式體,一個被宣告為靜態的變數在這一函式被呼叫過程中維持其值不變。
2). 在模組內(但在函式體外),一個被宣告為靜態的變數可以被模組內所用函式訪問,但不能被模組外其它函式訪問。它是一個本地的全域性變數。
3). 在模組內,一個被宣告為靜態的函式只可被這一模組內的其它函式呼叫。那就是,這個函式被限制在宣告它的模組的本地範圍內使用。 大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個應試者的嚴重的缺點,因為他顯然不懂得本地化數 據和程式碼範圍的好處和重要性。
16、#define MAX_LEN 500 char arry[MAX_LEN]; cin>>arry; 這段程式碼有問題嗎?若有,請指出並修改;
正確答案:
有問題。標頭檔案缺少。 #include <iostream>
17、delete []arry 和 delete arry 一樣嗎?不一樣請說明;
正確答案:
delete []arry 釋放的是多個同一型別的地址空間 Delete[]arry 釋放的是一個某種型別的地址空間
18、 多型的作用?
正確答案:
主要是兩個:
1)隱藏實現細節,使得程式碼能夠模組化;擴充套件程式碼模組,實現程式碼重用;
2)介面重用,為了類在繼承和派生的時候,保證使用家族中任一類的例項的某一屬性時的正確呼叫。
19、C語言的volatile的含義是什麼。使用時會對編譯器有什麼暗示。
正確答案:
終於最後一題了,容易麼……如果這個測試是一個關於嵌入式的,那麼這道題非常重要!!從詞面上講,volatile的意思是易變的,也就是說,在程式執行過程中,有一些變數可能會被莫名其妙的改變,而優化器為了節約時間,有時候不會重讀這個變數的真實值,而是去讀在暫存器的備份,這樣的話,這個變數的真實值反而被優化器給“優化”掉了,用時髦的詞說就是被“和諧”了。如果使用了這個修飾詞,就是通知編譯器別犯懶,老老實實去重新讀一遍!可能我說的太“通俗”了,那麼我引用一下“大師”的標準解釋: volatile的本意是“易變的” 。 由於訪問暫存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化,但有可能會讀髒資料。當要求使用volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。而且讀取的資料立刻被儲存。 精確地說就是,優化器在用到這個變數時必須每次都小心地重新讀取這個變數的值,而不是使用儲存在暫存器裡的備份。 下面是volatile變數的幾個例子:
1). 並行裝置的硬體暫存器(如:狀態暫存器)
2). 一箇中斷服務子程式中會訪問到的非自動變數(Non-automatic variables)
3). 多執行緒應用中被幾個任務共享的變數 嵌入式系統程式設計師經常同硬體、中斷、RTOS等等打交道,所用這些都要求volatile變數。不懂得volatile內容將會帶來災難。
20、 請簡述以下兩個for迴圈的優缺點
1)for (i=0; i<n; i++)
{
if (condition)
DoSomething();
else
DoOtherthing();
}
2)if (condition)
{
for (i=0; i<n; i++)
DoSomething();
}
else
{
for (i=0; i<n; i++)="" dootherthing();="" }=""
正確答案:
1)優點:程式簡潔。="" 缺點:多執行了n-1次邏輯判斷,並且打斷了迴圈“流水線”作業,使得編譯器不能對迴圈進行優化處理,降低了效率。=""
2)優點:迴圈的效率高。缺點:程式不簡潔。="
二、【百度C++面試題】
1、 前處理器標識#error的目的是什麼?
正確答案:
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的夥計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種 問題的答案。當然如果你不是在找一個書呆子,那麼應試者最好希望自己不要知道答案。
2、C語言的volatile的含義是什麼。使用時會對編譯器有什麼暗示。
正確答案:
終於最後一題了,容易麼……如果這個測試是一個關於嵌入式的,那麼這道題非常重要!!從詞面上講,volatile的意思是易變的,也就是說,在程式執行過程中,有一些變數可能會被莫名其妙的改變,而優化器為了節約時間,有時候不會重讀這個變數的真實值,而是去讀在暫存器的備份,這樣的話,這個變數的真實值反而被優化器給“優化”掉了,用時髦的詞說就是被“和諧”了。如果使用了這個修飾詞,就是通知編譯器別犯懶,老老實實去重新讀一遍!可能我說的太“通俗”了,那麼我引用一下“大師”的標準解釋: volatile的本意是“易變的” 。 由於訪問暫存器的速度要快過RAM,所以編譯器一般都會作減少存取外部RAM的優化,但有可能會讀髒資料。當要求使用volatile 宣告的變數的值的時候,系統總是重新從它所在的記憶體讀取資料,即使它前面的指令剛剛從該處讀取過資料。而且讀取的資料立刻被儲存。 精確地說就是,優化器在用到這個變數時必須每次都小心地重新讀取這個變數的值,而不是使用儲存在暫存器裡的備份。 下面是volatile變數的幾個例子: 1). 並行裝置的硬體暫存器(如:狀態暫存器) 2). 一箇中斷服務子程式中會訪問到的非自動變數(Non-automatic variables) 3). 多執行緒應用中被幾個任務共享的變數 嵌入式系統程式設計師經常同硬體、中斷、RTOS等等打交道,所用這些都要求volatile變數。不懂得volatile內容將會帶來災難。
3、 MFC中CString是型別安全類麼?
正確答案:
不是,其它資料型別轉換到CString可以使用CString的成員函式Format來轉換
4、行內函數INline和巨集定義一起使用的區別。
正確答案:
行內函數是在編譯的時候已經做好將對應的函式程式碼替換嵌入到對應的位置,適用於程式碼較少的函式。 巨集定義是簡單的替換變數,如果定義的是有引數的函式形式,引數不做型別校驗。
5、C++中什麼資料分配在棧或堆中,New分配資料是在近堆還是遠堆中?
正確答案:
棧: 存放區域性變數,函式呼叫引數,函式返回值,函式返回地址。由系統管理 堆: 程式執行時動態申請,new 和 malloc申請的記憶體就在堆上
6、DB事務處理的四個特性:
正確答案:
原子性,一致性,隔離性,永續性 就答對一個:一致性,
7、如何初始化一個指標陣列。
正確答案:
首先明確一個概念,就是指向陣列的指標,和存放指標的陣列。 指向陣列的指標:char (*array)[5];含義是一個指向存放5個字元的陣列的指標。 存放指標的陣列:char *array[5];含義是一個數組中存放了5個指向字元型資料的指標。 按照題意,我理解為初始化一個存放指標的陣列,char *array[2]={“China”,”Beijing”};其含義是初始化了一個有兩個指向字元型資料的指標的陣列,這兩個指標分別指向字串”China”和”Beijing”。
8、 int i=(j=4,k=8,l=16,m=32); printf(“%d”, i); 輸出是多少?
正確答案:
相當於 i=j=4;i=k=8;i=l=16;i=m=32; 故最後i=32;
9、如何在C中初始化一個字元陣列。
正確答案:
這個問題看似很簡單,但是我們要將最簡單的問題用最嚴謹的態度來對待。關鍵的地方:初始化、字元型、陣列。最簡單的方法是char array[];。這個問題看似解決了,但是在初始化上好像還欠缺點什麼,個人認為:char array[5]={’1′,’2′,’3′,’4′,’5′};或者char array[5]={“12345″};或者char array[2][10]={“China”,”Beijing”};也許更符合“初始化”的意思。
10、引數傳遞有幾種方式;實現多型引數傳遞採用什麼方式,如果沒有使用某種方式原因是什麼;
正確答案:
傳值,傳指標或者引用
11、請填寫BOOL , float, 指標變數 與“零值”比較的 if 語句。
正確答案:
這裡“零值”可以是0, 0.0 , FALSE或者“空指標”。例如 int 變數 n 與“零值”比較的 if 語句為:
if ( n == 0 )
if ( n != 0 )
12、C++特點是什麼,如何實現多型?畫出基類和子類在記憶體中的相互關係。
正確答案:
多型的基礎是繼承,需要虛擬函式的支援,簡單的多型是很簡單的。 子類繼承父類大部分的資源,不能繼承的有建構函式,解構函式,拷貝建構函式,operator=函式,友元函式等等
13、 什麼是“引用”?申明和使用“引用”要注意哪些問題?
正確答案:
引用就是某個目標變數的“別名”(alias),對應用的操作與對變數直接操作效果完全相同。申明一個引用的時候,切記要對其進行初始化。引 用宣告完畢後,相當於目標變數名有兩個名稱,即該目標原名稱和引用名,不能再把該引用名作為其他變數名的別名。宣告一個引用,不是新定義了一個變數,它只 表示該引用名是目標變數名的一個別名,它本身不是一種資料型別,因此引用本身不佔儲存單元,系統也不給引用分配儲存單元。不能建立陣列的引用。
14、觸發器怎麼工作的?
正確答案:
觸發器主要是通過事件進行觸發而被執行的,當對某一表進行諸如UPDATE、 INSERT、 DELETE 這些操作時,資料庫就會自動執行觸發器所定義的SQL 語句,從而確保對資料的處理必須符合由這些SQL 語句所定義的規則。
15、C也可以通過精心封裝某些函式功能實現重用,那C++的類有什麼優點嗎,難道僅僅是為實現重用。
正確答案:
並不僅僅是這樣的。 OOD,OOP從根本上改變了程式設計模式和設計思想,具備重大和深遠的意義。 類的三大最基本的特徵:封裝,繼承,多型.
16、CSingleLock是幹什麼的。
正確答案:
同步多個執行緒對一個數據類的同時訪問
17、 C++中引用和指標的區別?
正確答案:
引用是物件的別名, 操作引用就是操作這個物件, 必須在建立的同時有效得初始化(引用一個有效的物件, 不可為NULL), 初始化完畢就再也不可改變, 引用具有指標的效率, 又具有變數使用的方便性和直觀性, 在語言層面上引用和物件的用法一樣, 在二進位制層面上引用一般都是通過指標來實現的, 只是編譯器幫我們完成了轉換。 之所以使用引用是為了用適當的工具做恰如其分的事, 體現了最小特權原則。
18、 C與C++各自是如何定義常量的?有什麼不同?
正確答案:
C中是使用巨集#define定義, C++使用更好的const來定義。 區別: 1)const是有資料型別的常量,而巨集常量沒有,編譯器可以對前者進行靜態型別安全檢查,對後者僅是字元替換,沒有型別安全檢查,而且在字元替換時可能會產生意料不到的錯誤(邊際效應)。 2)有些編譯器可以對const常量進行除錯, 不能對巨集除錯。
19、 C++函式中值的傳遞方式有哪幾種?
正確答案:
C++函式的三種傳遞方式為:值傳遞、指標傳遞和引用傳遞。
20、一般資料庫若出現日誌滿了,會出現什麼情況,是否還能使用?
正確答案:
只能執行查詢等讀操作,不能執行更改,備份等寫操作,原因是任何寫操作都要記錄日誌。也就是說基本上處於不能使用的狀態。
三、【騰訊C++面試題】
1、.C++裡面如何宣告constvoidf(void)函式為C程式中的庫函式?
正確答案:
在該函式前新增extern “C”宣告。由於編譯後的名字不同,C++程式不能直接呼叫C 函式。
2、c++中類和c語言中struct的區別(至少兩點)
正確答案:
(1)c++中的類預設的成員是私有的,struct預設的是共有的。
(2)c++中的類可以定義成員函式,struct只能定義成員變數。
(3)C++中的類有繼承、多型的特性,struct沒有。
3、IP組播有那些好處?
正確答案:
Internet上產生的許多新的應用,特別是高頻寬的多媒體應用,帶來了頻寬的急劇消耗和網路擁擠問題。組播是一種允許一個或多個傳送者(組播源)傳送單一的資料包到多個接收者(一次的,同時的)的網路技術。組播可以大大的節省網路頻寬,因為無論有多少個目標地址,在整個網路的任何一條鏈路上只傳送單一的資料包。所以說組播技術的核心就是針對如何節約網路資源的前提下保證服務質量。
4、變數的宣告和定義有什麼區別?
正確答案:
宣告變數不分配空間,定義變數要分配空間。宣告主要是告訴編譯器,後面的引用都按宣告的格式。定義其實包含了宣告的意思,同時要分配記憶體空間。
5、程式什麼時候應該使用執行緒,什麼時候單執行緒效率高。
正確答案:
1 耗時的操作使用執行緒,提高應用程式響應
2 並行操作時使用執行緒,如C/S架構的伺服器端併發執行緒響應使用者的請求。
3 多CPU系統中,使用執行緒提高CPU利用率
4 改善程式結構。一個既長又複雜的程序可以考慮分為多個執行緒,成為幾個獨立或半獨立的執行部分,這樣的程式會利於理解和修改。
其他情況都使用單執行緒。
6、介紹一下模板和容器。如何實現?(也許會讓你當場舉例實現)
正確答案:
模板可以說比較古老了,但是當前的泛型程式設計實質上就是模板程式設計。 它體現了一種通用和泛化的思想。 STL有7種主要容器:vector,list,deque,map,multimap,set,multiset.
7、以下為WindowsNT下的32位C++程式,請計算sizeof的值
charstr[]=“Hello”;
char*p=str;
intn=10;
//請計算
sizeof(str)=?
sizeof(p)=?
sizeof(n)=?
voidFunc(charstr[100])
{
//請計算
sizeof(str)=?
}
void*p=malloc(100);
//請計算
sizeof(p)=?
正確答案:
sizeof (str ) = 6
sizeof ( p ) = 4
sizeof ( n ) =4
void Func ( char str[100])
{
sizeof( str ) = 4
}
void *p = malloc( 100 );
sizeof ( p ) =4
8、C語言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什麼?inta=5,b=7,c;c=a+++b;
正確答案:
這個問題將做為這個測驗的一個愉快的結尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理儘可能所有合法的用法。因此,上面的程式碼被處理成: c = a++ + b; 因此, 這段程式碼持行後a = 6, b = 7, c = 12。 如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個當作問題。我發現這個問題的最大好處是:這是一個關於程式碼編寫風格,程式碼的可讀性,程式碼的可修改性的好的話題
9、#include與#include“file.h”的區別?
正確答案:
前者是從Standard Library的路徑尋找和引用file.h,而後者是從當前工作路徑搜尋並引用file.h。
10、如何在C中初始化一個字元陣列。
正確答案:
這個問題看似很簡單,但是我們要將最簡單的問題用最嚴謹的態度來對待。關鍵的地方:初始化、字元型、陣列。最簡單的方法是char array[];。這個問題看似解決了,但是在初始化上好像還欠缺點什麼,個人認為:char array[5]={’1′,’2′,’3′,’4′,’5′};或者char array[5]={“12345″};或者char array[2][10]={“China”,”Beijing”};也許更符合“初始化”的意思。
11、在C++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern“C”?
正確答案:
extern是C/C++語言中表明函式和全域性變數作用範圍(可見性)的關鍵字,其宣告的函式和變數可以在本模組或其它模組中使用。 通常,在模組的標頭檔案中對本模組提供給其它模組引用的函式和全域性變數以關鍵字extern宣告。
12、記憶體的分配方式的分配方式有幾種?
正確答案:
1)從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個執行期間都存在。例如全域性變數。
2)在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。
3)從堆上分配,亦稱動態記憶體分配。程式在執行的時候用malloc或new申請任意多少的記憶體,程式設計師自己負責在何時用free或delete釋放記憶體。動態記憶體的生存期由我們決定,使用非常靈活,但問題也最多。
13、在C++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern"C"?
正確答案:
C++語言支援函式過載,C語言不支援函式過載。函式被C++編譯後在庫中的名字與C語言的不同。假設某個函式的原型為: void foo(int x, int y);該函式被C編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連線交換指定符號extern"C"來解決名字匹配問題。
14、如何讓區域性變數具有全域性生命期。
正確答案:
具體的生命期的概念我覺得我還要好好深入的學習一下,但是這個題目還算比較簡單,即用static修飾就可以了,但是隻是生命期延長,範圍並沒有擴大,除非把這個變數定義在函式體外的靜態區,不過那樣就變成全域性變量了,彷彿不符合題目要求。
15、解釋堆和棧的區別。
正確答案:
具體的生命期的概念我覺得我還要好好深入的學習一下,但是這個題目還算比較簡單,即用static修飾就可以了,但是隻是生命期延長,範圍並沒有擴大,除非把這個變數定義在函式體外的靜態區,不過那樣就變成全域性變量了,彷彿不符合題目要求。
16、在C++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern“C”宣告?
正確答案:
函式和變數被C++編譯後在符號庫中的名字與C語言的不同,被extern “C”修飾的變數和函式是按照C語言方式編譯和連線的。由於編譯後的名字不同,C++程式不能直接呼叫C 函式。C++提供了一個C 連線交換指定符號extern“C”來解決這個問題。
17、strtok函式在使用上要注意什麼問題。
正確答案:
這個問題我不知道能不能回答全面,因為實在是用的很少。這個函式的作用是分割字串,但是要分割的字串不能是常量,這是要注意的。比如先定義一個字串:char array[]=”part1,part2″;,strtok的原形是char *strtok(char *string, char *delim);,我們將”,”作為分隔符,先用pt=strtok(array,”,”);,得到的結果print出來就是”part1″,那後面的呢,要寫成pt=strtok(NULL,”,”);,注意,要用NULL,如果被分割的字串會被分成N段,那從第二次開始就一直要用NULL。總結起來,需要注意的是:被分割的字串和分隔符都要使用變數;除第一次使用指向字串的指標外,之後的都要使用NULL;注意使用這個函式的時候千萬別把指標跟丟了,不然就全亂了。
18、用預處理指令#define宣告一個常數,用以表明1年中有多少秒(忽略閏年問題)
正確答案:
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL 我在這想看到幾件事情:
1). #define 語法的基本知識(例如:不能以分號結束,括號的使用,等等)
2). 懂得前處理器將為你計算常數表示式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。 3). 意識到這個表示式將使一個16位機的整型數溢位-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。
4). 如果你在你的表示式中用到UL(表示無符號長整型),那麼你有了一個好的起點。記住,第一印象很重要。
19、說一說C與C++的記憶體分配方式?
正確答案:
1)從靜態儲存區域分配。記憶體在程式編譯的時候就已經分配好,這塊記憶體在程式的整個執行期間都存在,如全域性變數,static變數。
2)在棧上建立。在執行函式時,函式內區域性變數的儲存單元都可以在棧上建立,函式執行結束時這些儲存單元自動被釋放。棧記憶體分配運算內置於處理器的指令集中,效率很高,但是分配的記憶體容量有限。
3)從堆上分配(動態記憶體分配)程式在執行的時候用malloc或new申請任意多少的記憶體,程式設計師負責在何時用free或delete釋放記憶體。動態記憶體的生存期自己決定,使用非常靈活。
20、你如何理解MVC。簡單舉例來說明其應用。
正確答案:
MVC模式是observer 模式的一個特例,典型的有MFC裡面的文件檢視架構。
四、【華為C++面試題】
1、在C++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern“C”宣告?
正確答案:
二者的編譯器不同
2、inti=(j=4,k=8,l=16,m=32);printf(“%d”,i);輸出是多少?
正確答案:
相當於i=j=4;i=k=8;i=l=16;i=m=32;故最後i=32;
3、#include與#include“file.h”的區別?
正確答案:
相當於i=j=4;i=k=8;i=l=16;i=m=32;故最後i=32;
4、既然C++中有更好的const為什麼還要使用巨集?
正確答案:
相當於i=j=4;i=k=8;i=l=16;i=m=32;故最後i=32;
5、過載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?
正確答案:
從定義上來說:過載:是指允許存在多個同名函式,而這些函式的引數表不同(或許引數個數不同,或許引數型別不同,或許兩者都不同)。重寫:是指子類重新定義復類虛擬函式的方法。從實現原理上來說:過載:編譯器根據函式不同的引數表,對同名函式的名稱做修飾,然後這些同名函式就成了不同的函式。重寫:當子類重新定義了父類的虛擬函式後,父類指標根據賦給它的不同的子類指標,動態的呼叫屬於子類的該函式,這樣的函式呼叫在編譯期間是無法確定的(呼叫的子類的虛擬函式的地址無法給出)。
6、C++和C定義結構的分別是什麼。
正確答案:
Clanguage的結構僅僅是資料的結合Cplusplus的struct和class其實具備幾乎一樣的功能,只是預設的訪問屬性不一樣而已。
7、#include和#include"a.h"有什麼區別?
正確答案:
對於#include,編譯器從標準庫路徑開始搜尋a.h對於#include"a.h",編譯器從使用者的工作路徑開始搜尋a.h
8、#include和#include“filename.h”有什麼區別?
正確答案:
前者用來包含開發環境提供的庫標頭檔案,後者用來包含自己編寫的標頭檔案。
9、C函式可否單獨編譯?
正確答案:
外部函式,可以在開始引進來
10、請簡述以下兩個for迴圈的優缺點
1)for(i=0;i<n;i++)
{
if(condition)
DoSomething();
else
DoOtherthing();
}
2)if(condition)
{
for(i=0;i<n;i++)
DoSomething();
}
else
{
for(i=0;i<n;i++)=""dootherthing();=""}=""
正確答案:
1)優點:程式簡潔。缺點:多執行了n-1次邏輯判斷,並且打斷了迴圈“流水線”作業,使得編譯器不能對迴圈進行優化處理,降低了效率。
2)優點:迴圈的效率高。缺點:程式不簡潔。
11、完成程式,實現對陣列的降序排序
#include
voidsort(intarray[]);
intmain()
{
intarray[]={45,56,76,234,1,34,23,2,3};//數字任//意給出
sort(array);
return0;
}
voidsort(intarray[])
{____________________________________
inti,j,k;
for(i=1;i<=7;i++){if(array[i]>array[i-1])
{
k=ARRAY[i];
j=i-1;
do
{
array[j+1]=array[j];
j–;
}
while(k>array[j]&&j>=0);
array[j+1]=k;
}
}
—————————————————–
}
12、delete[]arry和deletearry一樣嗎?不一樣請說明;
正確答案:
delete[]arry釋放的是多個同一型別的地址空間Delete[]arry釋放的是一個某種型別的地址空間
13、結合1個你認為比較能體現OOP思想的專案,用UML來描述。
正確答案:
(最好這個專案繼承,多型,虛擬函式都有體現)這個問題大概會佔面試時間的一半,並且會問很多問題,一不小心可能會被問住)
14、C與C++各自是如何定義常量的?有什麼不同?
正確答案:
C中是使用巨集#define定義,C++使用更好的const來定義。區別:1)const是有資料型別的常量,而巨集常量沒有,編譯器可以對前者進行靜態型別安全檢查,對後者僅是字元替換,沒有型別安全檢查,而且在字元替換時可能會產生意料不到的錯誤(邊際效應)。2)有些編譯器可以對const常量進行除錯,不能對巨集除錯。
15、標頭檔案中的ifndef/define/endif幹什麼用?
正確答案:
防止重複定義
16、C++中為什麼用模板類。
正確答案:
(1)可用來建立動態增長和減小的資料結構
(2)它是型別無關的,因此具有很高的可複用性。
(3)它在編譯時而不是執行時檢查資料型別,保證了型別安全
(4)它是平臺無關的,可移植性
(5)可用於基本資料型別
17、動態連線庫的兩種方式?
正確答案:
呼叫一個DLL中的函式有兩種方法:1載入時動態連結(load-timedynamiclinking),模組非常明確呼叫某個匯出函式,使得他們就像本地函式一樣。這需要連結時連結那些函式所在DLL的匯入庫,匯入庫向系統提供了載入DLL時所需的資訊及DLL函式定位。2執行時動態連結(run-timedynamiclinking),執行時可以通過LoadLibrary或LoadLibraryEx函式載入DLL。DLL載入後,模組可以通過呼叫GetProcAddress獲取DLL函式的出口地址,然後就可以通過返回的函式指標呼叫DLL函數了。如此即可避免匯入庫檔案了。
18、在什麼時候需要使用“常引用”?
正確答案:
如果既要利用引用提高程式的效率,又要保護傳遞給函式的資料不在函式中被改變,就應使用常引用。常引用宣告方式:const型別識別符號&引用名=目標變數名;
19、前處理器標識#error的目的是什麼?
正確答案:
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的夥計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書呆子,那麼應試者最好希望自己不要知道答案。
20、GCC3.2.2版本中支援哪幾種程式語言。
正確答案:
這個問題實在變態,就像問你#error的作用是什麼一樣。不可否認,gcc是linux下一個亮點,是一個備受無數程式設計師推崇的編譯器,其優點省略1000字,有興趣可以自己查,我翻了翻書,書上曰:支援C,C++,Java,Obj-C,Ada,Fortran,Pascal,Modula-3等語言,這個“等”比較要命,不過我認為已經很全了,如果認為還是不全,乾脆把ASM也加上算了,不過那已經不算是編譯了。
五、【小米C++面試題】
1、已知strcpy的函式原型:char*strcpy(char*strDest,constchar*strSrc)其中strDest是目的字串,strSrc是源字串。不呼叫C++/C的字串庫函式,請編寫函式strcpy。
正確答案:
char*strcpy(char*strDest,constchar*strSrc)
{
if(strDest==NULL||strSrc==NULL)
returnNULL;
if(strDest==strSrc)
returnstrDest;
char*tempptr=strDest;
while((*strDest++=*strSrc++)!=‘\0’)
;
returntempptr;
}
2、
char*GetMemory(void)
{
charp[]="helloworld";
returnp;
}
voidTest(void)
{
char*str=NULL;
str=GetMemory();
printf(str);
}
請問執行Test函式會有什麼樣的結果?
正確答案:亂碼
3、過載(overload)和重寫(overried,有的書也叫做“覆蓋”)的區別?
正確答案:
從定義上來說:過載:是指允許存在多個同名函式,而這些函式的引數表不同(或許引數個數不同,或許引數型別不同,或許兩者都不同)。重寫:是指子類重新定義復類虛擬函式的方法。從實現原理上來說:過載:編譯器根據函式不同的引數表,對同名函式的名稱做修飾,然後這些同名函式就成了不同的函式。重寫:當子類重新定義了父類的虛擬函式後,父類指標根據賦給它的不同的子類指標,動態的呼叫屬於子類的該函式,這樣的函式呼叫在編譯期間是無法確定的(呼叫的子類的虛擬函式的地址無法給出)。
4、多重繼承如何消除向上繼承的二義性。
正確答案:
使用虛擬繼承即可.
5、#include與#include“file.h”的區別?
正確答案:
前者是從StandardLibrary的路徑尋找和引用file.h,而後者是從當前工作路徑搜尋並引用file.h。
6、對資料庫的一張表進行操作,同時要對另一張表進行操作,如何實現?
正確答案:
將操作多個表的操作放入到事務中進行處理
7、#include<filename.h>和#include“filename.h”有什麼區別?
正確答案:
查詢範圍不同,後者先查詢工作路徑,再查詢VC標準路徑;前者只查工作路徑。
8、前處理器標識#error的目的是什麼?
正確答案:
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的夥計和一個書呆子是很有用的。只有書呆子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書呆子,那麼應試者最好希望自己不要知道答案。
9、標頭檔案的作用是什麼?
正確答案:
1)通過標頭檔案來呼叫庫功能。
2)標頭檔案能加強型別安全檢查。
10、
voidGetMemory(char*p)
{
p=(char*)malloc(100);
}
voidTest(void)
{
char*str=NULL;
GetMemory(str);
strcpy(str,"helloworld");
printf(str);
}
請問執行Test函式會有什麼樣的結果?
正確答案:
程式崩潰了
11、delete[]arry和deletearry一樣嗎?不一樣請說明;
正確答案:
delete[]arry釋放的是多個同一型別的地址空間Delete[]arry釋放的是一個某種型別的地址空間
12、
VoidGetMemory(char**p,intnum){
*p=(char*)malloc(num);
}
voidTest(void){
char*str=NULL;
GetMemory(&str,100);
strcpy(str,“hello”);
printf(str);
}
請問執行Test函式會有什麼樣的結果?
正確答案:
輸出“hello”
13、請簡述以下兩個for迴圈的優缺點
//第一個
for(i=0;i<N;i++)
{
if(condition)
DoSomething();
else
DoOtherthing();
}
//第二個
if(condition)
{
for(i=0;i<N;i++)
DoSomething();
}
else
{
for(i=0;i<N;i++)
DoOtherthing();
}
正確答案:
先迴圈再判斷,先判斷再迴圈第一個優點:每個迴圈都先判斷,再執行第二個優點:條件判斷,只發生其中一個行為
14、建構函式可否是虛汗數,為什麼?解構函式呢,可否是純虛的呢?
正確答案:
錯題解析:建構函式不能為虛擬函式,要構造一個物件,必須清楚地知道要構造什麼,否則無法構造一個物件。解構函式可以為純虛擬函式。
15、在C++程式中呼叫被C編譯器編譯後的函式,為什麼要加extern"C"?
正確答案:
C++語言支援函式過載,C語言不支援函式過載。函式被C++編譯後在庫中的名字與C語言的不同。假設某個函式的原型為:voidfoo(intx,inty);該函式被C編譯器編譯後在庫中的名字為_foo,而C++編譯器則會產生像_foo_int_int之類的名字。C++提供了C連線交換指定符號extern"C"來解決名字匹配問題。
16、請寫出下面程式碼在32位平臺上的執行結果,並說明sizeof的性質:
#include
#include
intmain(void)
{
chara[30];
char*b=(char*)malloc(20*sizeof(char));
printf(“%d\n”,sizeof(a));
printf(“%d\n”,sizeof(b));
printf(“%d\n”,sizeof(a[3]));
printf(“%d\n”,sizeof(b+3));
printf(“%d\n”,sizeof(*(b+4)));
return0;
}
正確答案:
在32位系統下(如WIN32),指標長度為32位。a是一個有30個元素的字元型陣列;b是一個字串指標;a[3]是字元型;b+3是指標;*(b+4)是字元型。因此輸出:30、4、1、4、1
17、高階通訊包括訊號量,——-,——–
正確答案:
通常把訊號、訊號量通訊稱為低階通訊,而把管道、訊息佇列、共享儲存區通訊稱為高階通訊,這個題目我也不知道怎麼填了,。。。。。。
18、關聯、聚合(Aggregation)以及組合(Composition)的區別?
正確答案:
涉及到UML中的一些概念:關聯是表示兩個類的一般性聯絡,比如“學生”和“老師”就是一種關聯關係;聚合表示has-a的關係,是一種相對鬆散的關係,聚合類不需要對被聚合類負責,如下圖所示,用空的菱形表示聚合關係:從實現的角度講,聚合可以表示為:classA{…}classB{A*a;…..}而組合表示contains-a的關係,關聯性強於聚合:組合類與被組合類有相同的生命週期,組合類要對被組合類負責,採用實心的菱形表示組合關係:實現的形式是:classA{…}classB{Aa;…}
19、儘管不像非嵌入式計算機那麼常見,嵌入式系統還是有從堆(heap)中動態分配記憶體的過程的。那麼嵌入式系統中,動態分配記憶體可能發生的問題是什麼?
正確答案:
這裡,我期望應試者能提到記憶體碎片,碎片收集的問題,變數的持行時間等等。這個主題已經在ESP雜誌中被廣泛地討論過了(主要是選項:J.Plauger,他的解釋遠遠超過我這裡能提到的任何解釋),所有回過頭看一下這些雜誌吧!讓應試者進入一種虛假的安全感覺後,我拿出這麼一個小節目:下面的程式碼片段的輸出是什麼,為什麼?
char*ptr;
if((ptr=(char*)malloc(0))==NULL)
puts("Gotanullpointer");
else
puts("Gotavalidpointer");
這是一個有趣的問題。最近在我的一個同事不經意把0值傳給了函式malloc,得到了一個合法的指標之後,我才想到這個問題。這就是上面的程式碼,該程式碼的輸出是“Gotavalidpointer”。我用這個來開始討論這樣的一問題,看看被面試者是否想到庫例程這樣做是正確。得到正確的答案固然重要,但解決問題的方法和你做決定的基本原理更重要些。
20、
voidTest(void){
char*str=(char*)malloc(100);
strcpy(str,“hello”);
free(str);
if(str!=NULL){
strcpy(str,“world”);
printf(str);
}
}
請問執行Test函式會有什麼樣的結果?
正確答案:
錯題解析:輸出“world”
改變自己,從現在做起-----------久館
&n