校招八股:C/C++開發(fā)工程師常見筆試耘分、面試題目匯總【基礎(chǔ)】

這里匯總一些C/C++開發(fā)崗的常見面試八股題,都屬于比較基礎(chǔ)绑警、偏理論性的題目求泰。換句話說,如果這些題目答不上來计盒,可能會(huì)給面試官留下的基礎(chǔ)不好的印象渴频,尤其是科班生哈。

廢話不多說北启,直接開始卜朗。

一、C/C++篇

1. 基礎(chǔ)中的基礎(chǔ)篇

簡述C和C++的區(qū)別

難度:? 被考頻率:???

如果你面試的是C++開發(fā)崗咕村,有些面試官會(huì)把這個(gè)問題作為第一個(gè)問題场钉。C和C++的區(qū)別細(xì)究起來的話太多了,因此懈涛,我們只要回答它們最大的逛万,也是最主要的區(qū)別就好了。如果面試官想知道其余細(xì)節(jié)的話會(huì)繼續(xù)追問的批钠。

C和C++的區(qū)別如下:

  1. 思想上:C是面向過程的宇植,它的主要特點(diǎn)是函數(shù)得封。編程思想是將問題分解成不同的步驟,并調(diào)用函數(shù)來依次實(shí)現(xiàn)這些步驟指郁。
    C++是面向?qū)ο蟮拿ι希闹饕攸c(diǎn)是類和對象。編程思想是將數(shù)據(jù)和數(shù)據(jù)操作封裝成不同的類闲坎,通過創(chuàng)建這些類的對象并調(diào)用對象的成員函數(shù)來實(shí)現(xiàn)對數(shù)據(jù)模型的操作晨横。

  2. 應(yīng)用上:C的應(yīng)用更偏底層,常常用于嵌入式開發(fā)箫柳、驅(qū)動(dòng)開發(fā)等直接與硬件交互的領(lǐng)域。
    C++由于它優(yōu)秀的面向?qū)ο髾C(jī)制啥供,在大型應(yīng)用程序的開發(fā)方面也表現(xiàn)出色悯恍。

  3. C++是對C的擴(kuò)充。除了添加了面向?qū)ο髾C(jī)制以外伙狐,C++還添加的機(jī)制常用到的有:類模板涮毫、異常處理、運(yùn)算符重載贷屎、標(biāo)準(zhǔn)模板庫(STL)罢防、命名空間(namespace)、流(stream)等等唉侄。

C程序從源程序到二進(jìn)制機(jī)器代碼的過程和gcc指令

難度:?? 被考頻率:???

舉例:gcc編譯源代碼hello.c的過程咒吐。


編譯過程

1. 預(yù)處理(Preprocessing):gcc -E hello.c -o hello.i
處理所有預(yù)編譯指令,即源代碼文件中以“#”開頭的指令属划,具體為:
a. 展開宏定義#define恬叹。
b. 處理?xiàng)l件編譯指令#ifdef。
c. 處理文件包含指令#include同眯。
d. 刪除注釋"http://"和"/* */"绽昼。
e. 添加行號(hào)和文件標(biāo)識(shí),便于編譯器在編譯階段產(chǎn)生錯(cuò)誤和警告提示時(shí)能夠顯示行號(hào)须蜗。

2. 編譯(Compilation):gcc -S hello.i -o hello.s
對預(yù)處理后的文件進(jìn)行詞法分析硅确、語法分析、語義分析明肮、中間代碼的生成和優(yōu)化菱农,最后得到匯編代碼文件。
a. 詞法分析(Lexical analysis):詞法分析器會(huì)從左到右逐個(gè)字符讀入源程序晤愧,按照詞法規(guī)則將源代碼分割成一個(gè)個(gè)單詞(Token)大莫,檢查詞法錯(cuò)誤,并輸出二元組<單詞類別官份,單詞屬性>方便后續(xù)編譯過程的引用只厘。
b. 語法分析(Syntax analysis):識(shí)別由詞法分析器輸出的單詞符號(hào)序列烙丛,構(gòu)造一棵語法樹。語法樹指出了詞法單元流的語法結(jié)構(gòu)羔味,可以判斷是否符合語法規(guī)范河咽。常見的語法分析方法分為自下而上和自上而下兩大方法。
c. 語義分析(Semantic analysis):使用語法樹和單詞符號(hào)表中的信息赋元,進(jìn)一步檢查源程序是否滿足語言定義的語義約束忘蟹。這一步分析的時(shí)靜態(tài)語義,也就是在編譯期間能分析的語義搁凸,而動(dòng)態(tài)語義指在運(yùn)行期間才能確定的語義媚值。
d. 中間代碼生成:根據(jù)語義分析的輸出,生成類機(jī)器語言的中間代碼护糖,如三地址代碼褥芒。
e. 中間代碼優(yōu)化:改進(jìn)中間代碼的質(zhì)量。
f. 目標(biāo)代碼生成:將中間代碼映射成目標(biāo)語言(匯編語言)嫡良。

3. 匯編(Assembly):gcc -c hello.s -o hello.o
匯編器將匯編代碼翻譯成可執(zhí)行的機(jī)器碼锰扶。每一條匯編語句對應(yīng)一條機(jī)器指令,因此匯編器的工作就是根據(jù)匯編指令和機(jī)器指令的對照表一一翻譯過來即可寝受。

4. 鏈接(Linking):gcc hello.o -o hello
鏈接器將多個(gè)匯編后得到的機(jī)器碼文件鏈接坷牛,從而生成一個(gè)可執(zhí)行程序。分為靜態(tài)鏈接和動(dòng)態(tài)鏈接兩種方式很澄。
a. 靜態(tài)鏈接:在鏈接可執(zhí)行文件時(shí)京闰,鏈接器會(huì)找到所有被用到的源代碼,將它們復(fù)制并組合起來形成一個(gè)可執(zhí)行文件甩苛。優(yōu)點(diǎn)是由于可執(zhí)行文件中已經(jīng)具備了執(zhí)行程序需要的全部內(nèi)容忙干,因此執(zhí)行時(shí)運(yùn)行速度較快。缺點(diǎn)是如果有多個(gè)可執(zhí)行程序需要引用同一個(gè)目標(biāo)文件浪藻,每個(gè)可執(zhí)行程序都會(huì)復(fù)制一份該文件的副本捐迫,造成空間浪費(fèi);另外爱葵,如果某個(gè)目標(biāo)文件被修改了施戴,則所有引用該文件的可執(zhí)行程序都需要重新編譯。
b. 動(dòng)態(tài)鏈接:程序被拆分成獨(dú)立的部分存儲(chǔ)萌丈,只有運(yùn)行時(shí)才鏈接在一起形成完整的程序赞哗。優(yōu)點(diǎn)是即使多個(gè)程序依賴同一個(gè)動(dòng)態(tài)鏈接庫,也不需要將這個(gè)庫復(fù)制多份辆雾,而是所有程序共享這個(gè)庫肪笋;此外在程序更新時(shí)只更新被修改的庫,不需要重新鏈接所有程序。缺點(diǎn)是因?yàn)閷㈡溄舆^程推遲到程序運(yùn)行時(shí)期藤乙,所以會(huì)對程序性能產(chǎn)生損失猜揪。

C程序的內(nèi)存管理

難度:?? 被考到頻率:????

C或C++語言編寫的程序在處理機(jī)上運(yùn)行,通常被分成五段:

  1. 棧區(qū):存放函數(shù)中聲明的局部變量坛梁、函數(shù)的形參和返回值垫挨。地址空間“向下減少”状蜗。

  2. 堆區(qū):保存動(dòng)態(tài)分配的內(nèi)存區(qū)域,可由程序員向操作系統(tǒng)申請和自行釋放话瞧。

  3. 靜態(tài)區(qū)(全局區(qū)):存儲(chǔ)全局變量和靜態(tài)變量育特。靜態(tài)區(qū)內(nèi)存程序開始時(shí)創(chuàng)建举反,直到程序運(yùn)行結(jié)束后才會(huì)被釋放蹂匹。

  4. 常量區(qū):保存常量岛都,在程序運(yùn)行期間不能被修改的量,如字符串常量"abcd"队魏。

  5. 代碼區(qū):存放程序代碼缔俄,二進(jìn)制機(jī)器指令形式,只讀器躏。

補(bǔ)充:一個(gè)由C語言程序編譯得到的可執(zhí)行二進(jìn)制文件,從硬盤上被加載到內(nèi)存空間上運(yùn)行的過程蟹略,內(nèi)存的分配和管理機(jī)制登失。

一個(gè)C語言編譯的可執(zhí)行二進(jìn)制文件,通常被分為三段:代碼段(text)挖炬、數(shù)據(jù)段(data)揽浙、堆棧段(BSS)。

裝載到內(nèi)存上被分為五段:棧區(qū)(stack)意敛、堆區(qū)(heap)馅巷、未初始化變量(BSS)、初始化變量(data)草姻、代碼段(text)钓猬。

可執(zhí)行文件中,text段存放二進(jìn)制程序撩独;data段存放靜態(tài)初始化的數(shù)據(jù)敞曹,即賦初值的全局變量和static變量;BSS段存放未初始化的數(shù)據(jù)综膀,即沒有賦初值的全局變量和static變量澳迫,在可執(zhí)行文件中BSS段并不占用實(shí)際空間,而是只記載該區(qū)大小的數(shù)值剧劝,程序載入時(shí)菜實(shí)際分配空間橄登,且該控件由系統(tǒng)初始化為零。

應(yīng)用程序加載到內(nèi)存空間時(shí),操作系統(tǒng)根據(jù)可執(zhí)行文件中header中的內(nèi)容拢锹,為text段谣妻、data段、為BSS段分配相應(yīng)的內(nèi)存空間面褐,將文件中
data段和text段內(nèi)容拷貝到內(nèi)存中拌禾,將BSS段初始化為零,同時(shí)為堆區(qū)和棧區(qū)分配空間并維護(hù)展哭。

內(nèi)存空間分配

堆和棧的區(qū)別

難度:?? 被考到頻率:?????

用戶自己申請 系統(tǒng)分配
由不連續(xù)的內(nèi)存塊構(gòu)成的鏈表湃窍,大小可以調(diào)整 連續(xù)空間,大小固定
速度慢匪傍,會(huì)產(chǎn)生碎片 速度快您市,不會(huì)產(chǎn)生碎片
向高地址增長 向低地址增長
由庫函數(shù)(malloc/realloc/free、new/delete)提供服務(wù) 由系統(tǒng)提供服務(wù)

什么叫內(nèi)存泄漏

難度:?? 被考到頻率:??

內(nèi)存泄漏役衡,通常指堆內(nèi)存泄漏茵休,程序員向系統(tǒng)申請任意大小的堆內(nèi)存塊,使用完畢必須進(jìn)行顯式的內(nèi)存釋放手蝎,否則該內(nèi)存不能再次被使用榕莺。即使用malloc、realloc棵介、new申請的空間钉鸯,必須使用free、delete進(jìn)行釋放邮辽。

什么叫作用域

2. C++特性篇

C++的三大特征

難度:? 被考到頻率:??

繼承唠雕、多態(tài)、封裝吨述。

  1. 繼承:一個(gè)對象可以繼承另一類對象的特征和能力岩睁。目的是避免公用代碼的重復(fù)開發(fā),減少代碼和數(shù)據(jù)冗余揣云。

  2. 多態(tài):為不同數(shù)據(jù)類型的實(shí)體提供統(tǒng)一的接口捕儒,程序運(yùn)行時(shí),相同的消息可能會(huì)送給多個(gè)不同的類別之對象邓夕,而系統(tǒng)可依據(jù)對象所屬類別肋层,引發(fā)對應(yīng)類別的方法,而有不同的行為

  3. 封裝:把客觀的事物抽象成一個(gè)類翎迁,就是將數(shù)據(jù)和方法打包在一起栋猖,加以權(quán)限的區(qū)分,達(dá)到保護(hù)并安全使用數(shù)據(jù)的目的汪榔。

靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)

難度:?? 被考到頻率:??

多態(tài)分為靜態(tài)多態(tài)和動(dòng)態(tài)多態(tài)蒲拉。

靜態(tài)多態(tài):在編譯期間決定程序的執(zhí)行過程肃拜。包括函數(shù)重載和泛型編程,泛型編程包括函數(shù)模板和類模板雌团。

動(dòng)態(tài)多態(tài):在程序運(yùn)行時(shí)根據(jù)被引用對象的實(shí)際類型判斷調(diào)用哪個(gè)方法燃领。包括虛函數(shù)。

C++中重載锦援、重寫(覆蓋)和隱藏的區(qū)別

難度:?? 被考到頻率:??

  1. 重載(overload):同一作用域存在的名稱相同猛蔽、參數(shù)類型或參數(shù)數(shù)目不同的函數(shù)。在函數(shù)調(diào)用時(shí)根據(jù)不同的參數(shù)來決定具體調(diào)用哪個(gè)函數(shù)灵寺。
class A {
   ...
    void fun(int);
    void fun(double, double);
   ...
}
  1. 重寫(覆蓋)(override)
    派生類中的函數(shù)覆蓋基類中的同名函數(shù)曼库,要求兩個(gè)函數(shù)具有相同的參數(shù)個(gè)數(shù)、參數(shù)類型和返回值類型略板,且基類中的函數(shù)必須是虛函數(shù)毁枯。重寫指的是重寫基類函數(shù)中的函數(shù)體。
class A { //父類
public:
    virtual int fun(int a) {...}
}

class B : public A { //子類
public:
    virtual int fun(int a) override {...} //重寫叮称,加override可以確保是重寫父類的函數(shù)
}
  1. 隱藏(hide)
    在某些情況下种玛,派生類中的函數(shù)屏蔽了基類中的同名函數(shù)的現(xiàn)象。如果想調(diào)用基類的函數(shù)必須加作用域限定符瓤檐。具體情況有:

(1)派生類和基類中具有同名函數(shù)赂韵,兩個(gè)函數(shù)參數(shù)列表相同,且基類的函數(shù)沒有被聲明稱虛函數(shù)挠蛉。

class A { //父類
public:
    void fun(int a) {...}
};

class B : public A { //子類
public:
    void fun(int a) {...} //隱藏父類的fun函數(shù)
};

int main() {
    B b;
    b.fun(2); //調(diào)用B中的fun函數(shù)
    b.A::fun(2); //調(diào)用A中fun函數(shù)
    return 0;
}

(2)派生類和基類中具有同名函數(shù)祭示,兩個(gè)函數(shù)參數(shù)列表不同,無論基類的函數(shù)是不是虛函數(shù)都會(huì)被隱藏碌秸。

class A { //父類
public:
    void fun(int a) {...}
};

class B : public A { //子類
public:
    void fun(char* a) {...} //隱藏父類的fun函數(shù)
};

int main() {
    B b;
    b.fun(2); //報(bào)錯(cuò),調(diào)用B中的fun函數(shù)悄窃,但參數(shù)類型出錯(cuò)
    b.A::fun(2); //調(diào)用A中fun函數(shù)
    return 0;
}

虛函數(shù)

難度:?? 被考到頻率:???

基類和派生類中可以出現(xiàn)名字相同讥电、參數(shù)個(gè)數(shù)和參數(shù)類型都相同的函數(shù),直接調(diào)用時(shí)編譯器會(huì)讓派生類函數(shù)覆蓋基類函數(shù)轧抗,或者通過添加作用域限定符來調(diào)用基類函數(shù)恩敌。因此,

下面的例子中横媚,基類和派生類中具有同名函數(shù)display()纠炮。

#include <iostream>
using namespace std;

//定義基類
class Point {
protected:
    float x, y;
public:
    Point(float x = 0, float y = 0); //構(gòu)造函數(shù)
    void display();
};

Point::Point(float a, float b) : x(a), y(b) {}
void Point::display() {
    cout << "[x, y] = [" << x << ", " << y << "]" << endl;
}

//定義派生類,繼承自父類Point
class Circle : public Point {
private:
    float radius;
public:
    Circle(float x = 0, float y = 0, float r = 0); //構(gòu)造函數(shù)
    void display(); //與基類中同名的函數(shù)
};

Circle::Circle(float a, float b, float r) : Point(a, b), radius(r) {}
void Circle::display() {
    cout << "[x, y] = [" << x << ", " << y << "]; r = " << radius << endl;
    return;
}

int main() {
    Point p(1, 1); //定義一個(gè)基類對象
    Circle c(5, 5, 2.5); //定義一個(gè)派生類對象
    Point* pt; //定義一個(gè)基類指針
    pt = &p;  //指針指向基類對象
    pt->display(); //調(diào)用同名函數(shù)
    pt = &c; //指針指向派生類對象
    pt->display(); //調(diào)用同名函數(shù)
    return 0;
}

輸出結(jié)果灯蝴。

[x, y] = [1, 1]
[x, y] = [5, 5]

分析輸出結(jié)果可以發(fā)現(xiàn)恢口,第一行調(diào)用的基類的成員函數(shù),第二行雖然指針指向了派生類穷躁,但由于指針的類型時(shí)基類的耕肩,調(diào)用的依舊是基類的成員函數(shù)。如果我們希望指針指向什么類的對象,就調(diào)用該類的成員函數(shù)猿诸,則需要將基類的display函數(shù)聲明為虛函數(shù)婚被。

修改代碼,其他地方不修改梳虽,只是在基類Point中的聲明display函數(shù)時(shí)添加關(guān)鍵字virtual址芯,如下。

//定義基類
class Point {
protected:
    float x, y;
public:
    Point(float x = 0, float y = 0); //構(gòu)造函數(shù)
    virtual void display();
};
... ...

運(yùn)行結(jié)果如下窜觉。

[x, y] = [1, 1]
[x, y] = [5, 5]; r = 2.5

在設(shè)定虛函數(shù)之前谷炸,基類指針本應(yīng)該指向基類對象,如果指向派生類對象竖螃,則必須進(jìn)行指針類型轉(zhuǎn)換淑廊,將派生類的指針轉(zhuǎn)換成基類指針,因此通過該指針也只能調(diào)用派生類對象中的基類部分特咆。

設(shè)定虛函數(shù)之后季惩,派生類的基類部分取代了原本基類中的虛函數(shù),因此即使基類指針指向派生類對象腻格,也會(huì)調(diào)用派生類中的成員函數(shù)画拾。

虛函數(shù)的原理

難度:??? 被考到頻率:??

實(shí)現(xiàn)原理:虛函數(shù)表+虛表指針

虛函數(shù)表(vtbl):是一個(gè)數(shù)組,每個(gè)元素都用來存儲(chǔ)虛函數(shù)的地址菜职。每個(gè)類有一個(gè)自己的虛函數(shù)表青抛,由于類中虛函數(shù)的個(gè)數(shù)可以在編譯時(shí)期就能確定,因此虛函數(shù)表的大小在編譯時(shí)期就可以確定酬核。虛函數(shù)表是全局共享的蜜另,存儲(chǔ)在全局?jǐn)?shù)據(jù)區(qū),在編譯時(shí)完成構(gòu)造嫡意,全局可用举瑰。

虛表指針(vptr):編譯器為每個(gè)類對象添加一個(gè)隱藏成員,隱藏成員保存了一個(gè)指向虛函數(shù)表的指針蔬螟,

未完待續(xù)……

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末此迅,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子旧巾,更是在濱河造成了極大的恐慌耸序,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,348評(píng)論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件鲁猩,死亡現(xiàn)場離奇詭異坎怪,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)廓握,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,122評(píng)論 2 385
  • 文/潘曉璐 我一進(jìn)店門芋忿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來炸客,“玉大人,你說我怎么就攤上這事戈钢”韵桑” “怎么了?”我有些...
    開封第一講書人閱讀 156,936評(píng)論 0 347
  • 文/不壞的土叔 我叫張陵殉了,是天一觀的道長开仰。 經(jīng)常有香客問我,道長薪铜,這世上最難降的妖魔是什么众弓? 我笑而不...
    開封第一講書人閱讀 56,427評(píng)論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮隔箍,結(jié)果婚禮上谓娃,老公的妹妹穿的比我還像新娘。我一直安慰自己蜒滩,他們只是感情好滨达,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,467評(píng)論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著俯艰,像睡著了一般捡遍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上竹握,一...
    開封第一講書人閱讀 49,785評(píng)論 1 290
  • 那天画株,我揣著相機(jī)與錄音,去河邊找鬼啦辐。 笑死谓传,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的芹关。 我是一名探鬼主播续挟,決...
    沈念sama閱讀 38,931評(píng)論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼充边!你這毒婦竟也來了庸推?” 一聲冷哼從身側(cè)響起常侦,我...
    開封第一講書人閱讀 37,696評(píng)論 0 266
  • 序言:老撾萬榮一對情侶失蹤浇冰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后聋亡,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體肘习,經(jīng)...
    沈念sama閱讀 44,141評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,483評(píng)論 2 327
  • 正文 我和宋清朗相戀三年坡倔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漂佩。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片脖含。...
    茶點(diǎn)故事閱讀 38,625評(píng)論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖投蝉,靈堂內(nèi)的尸體忽然破棺而出养葵,到底是詐尸還是另有隱情,我是刑警寧澤瘩缆,帶...
    沈念sama閱讀 34,291評(píng)論 4 329
  • 正文 年R本政府宣布关拒,位于F島的核電站,受9級(jí)特大地震影響庸娱,放射性物質(zhì)發(fā)生泄漏着绊。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,892評(píng)論 3 312
  • 文/蒙蒙 一熟尉、第九天 我趴在偏房一處隱蔽的房頂上張望归露。 院中可真熱鬧,春花似錦斤儿、人聲如沸剧包。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽玄捕。三九已至,卻和暖如春棚放,著一層夾襖步出監(jiān)牢的瞬間枚粘,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評(píng)論 1 265
  • 我被黑心中介騙來泰國打工飘蚯, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留馍迄,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,324評(píng)論 2 360
  • 正文 我出身青樓局骤,卻偏偏與公主長得像攀圈,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子峦甩,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,492評(píng)論 2 348

推薦閱讀更多精彩內(nèi)容