日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > c/c++ >内容正文

c/c++

二十万字C/C++、嵌入式软开面试题全集宝典七

發布時間:2025/3/15 c/c++ 19 豆豆
生活随笔 收集整理的這篇文章主要介紹了 二十万字C/C++、嵌入式软开面试题全集宝典七 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

目錄

121、 怎樣判斷兩個浮點數是否相等?

122、 宏定義一個取兩個數中較大值的功能

123、 define、const、typedef、inline使用方法?

124、 printf實現原理?

125、 #include 的順序以及尖括號和雙引號的區別

126、 lambda函數

127、 模板類和模板函數的區別是什么?

128、 為什么模板類一般都是放在一個h文件中

129、 C++中類成員的訪問權限和繼承權限問題。

130、 cout和printf有什么區別?

131、 重載運算符?

132、 函數重載函數匹配原則

133、 定義和聲明的區別

134、 全局變量和static變量的區別

135、 static函數與普通函數有什么區別?

136、 靜態成員與普通成員的區別

137、 說一下理解 ifdef endif

138、 隱式轉換,如何消除隱式轉換?

139、 虛函數的內存結構,那菱形繼承的虛函數內存結構呢

140、 多繼承的優缺點,作為一個開發者怎么看待多繼承


?

121、 怎樣判斷兩個浮點數是否相等?

對兩個浮點數判斷大小和是否相等不能直接用==來判斷,會出錯!明明相等的兩個數比較反而是不相等!對于兩個浮點數比較只能通過相減并與預先設定的精度比較,記得要取絕對值!浮點數與0的比較也應該注意。與浮點數的表示方式有關。
const float EPSINON = 0.00001;
if (((a-b) >= - EPSINON) && ((a-b) <= EPSINON);

122、 宏定義一個取兩個數中較大值的功能

#define MAX(x,y)((x>y?)x:y)

123、 define、const、typedef、inline使用方法?

一、const與#define的區別:
1.const定義的常量是變量帶類型,而#define定義的只是個常數不帶類型;
2.define只在預處理階段起作用,簡單的文本替換,而const在編譯、鏈接過程中起作用;
3.define只是簡單的字符串替換沒有類型檢查。而const是有數據類型的,是要進行判斷的,可以避免一些低級錯誤;
4.define預處理后,占用代碼段空間,const占用數據段空間;
5.const不能重定義,而define可以通過#undef取消某個符號的定義,進行重定義;
6.define獨特功能,比如可以用來防止文件重復引用。
二、#define和別名typedef的區別
1.執行時間不同,typedef在編譯階段有效,typedef有類型檢查的功能;#define是宏定義,發生在預處理階段,不進行類型檢查;
2.功能差異,typedef用來定義類型的別名,定義與平臺無關的數據類型,與struct的結合使用等。#define不只是可以為類型取別名,還可以定義常量、變量、編譯開關等。
3.作用域不同,#define沒有作用域的限制,只要是之前預定義過的宏,在以后的程序中都可以使用。而typedef有自己的作用域。
三、define與inline的區別
1.#define是關鍵字,inline是函數;
2.宏定義在預處理階段進行文本替換,inline函數在編譯階段進行替換;
3.inline函數有類型檢查,相比宏定義比較安全;

124、 printf實現原理?

1.在C/C++中,對函數參數的掃描是從后向前的。C/C++的函數參數是通過壓入堆棧的方式來給函數傳參數的(堆棧是一種先進后出的數據結構),最先壓入的參數最后出來,在計算機的內存中,數據有2塊,一塊是堆,一塊是棧(函數參數及局部變量在這里),而棧是從內存的高地址向低地址生長的,控制生長的就是堆棧指針了,最先壓入的參數是在高地址,最后壓入的參數在低地址,結構上看起來是第一個,所以最后壓入的參數總是能夠被函數找到,因為它就在堆棧指針的上方。
2.printf的第一個被找到的參數就是那個字符指針,就是被雙引號括起來的那一部分,函數通過判斷字符串里控制參數的個數來判斷參數個數及數據類型,通過這些就可算出數據需要的堆棧指針的偏移量了,下面給出printf("%d,%d",a,b);(其中a、b都是int型的)的匯編代碼.

125、 #include 的順序以及尖括號和雙引號的區別

1.<>尖括號表示編譯器只在系統默認目錄或尖括號內的工作目錄下搜索頭文件,并不去用戶的工作目錄下尋找,所以一般尖括號用于包含標準庫文件;
2.""雙引號表示編譯器先在用戶的工作目錄下搜索頭文件,如果搜索不到則到系統默認目錄下去尋找,所以雙引號一般用于包含用戶自己編寫的頭文件。

126、 lambda函數

1.定義
利用lambda表達式可以編寫內嵌的匿名函數,用以替換獨立函數或者函數對象;每當你定義一個lambda表達式后,編譯器會自動生成一個匿名類(這個類當然重載了()運算符),我們稱為閉包類型(closure type)。那么在運行時,這個lambda表達式就會返回一個匿名的閉包實例,其實一個右值。可以通過傳值或者引用的方式捕捉其封裝作用域內的變量,前面的方括號就是用來定義捕捉模式以及變量,我們又將其稱為lambda捕捉塊。
2.用法
lambda表達式的語法定義如下:
[capture list] (params list) mutable exception-> return type { function body }
各項具體含義如下:
capture list:捕獲外部變量列表
params list:形參列表
mutable指示符:用來說用是否可以修改捕獲的變量
exception:異常設定
return type:返回類型
function body:函數體
3.lamda的幾種捕獲方式

捕獲形式

說明

[]

不捕獲任何外部變量

[變量名, …]

默認以值得形式捕獲指定的多個外部變量(用逗號分隔),如果引用捕獲,需要顯示聲明(使用&說明符)

[this]

以值的形式捕獲this指針

[=]

以值的形式捕獲所有外部變量

[&]

以引用形式捕獲所有外部變量

[=, &x]

變量x以引用形式捕獲,其余變量以傳值形式捕獲

[&, x]

變量x以值的形式捕獲,其余變量以引用形式捕獲


4.lambda必須使用尾置返回來指定返回類型,可以忽略參數列表和返回值,但必須永遠包含捕獲列表和函數體;

127、 模板類和模板函數的區別是什么?

函數模板的實例化是由編譯程序在處理函數調用時自動完成的,而類模板的實例化必須由程序員在程序中顯式地指定。即函數模板允許隱式調用和顯式調用而類模板只能顯示調用。在使用時類模板必須加<T>,而函數模板不必。

128、 為什么模板類一般都是放在一個h文件中

1.模板定義很特殊。由template<…>處理的任何東西都意味著編譯器在當時不為它分配存儲空間,它一直處于等待狀態直到被一個模板實例告知。在編譯器和連接器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在頭文件中放置全部的模板聲明和定義。
2.在分離式編譯的環境下,編譯器編譯某一個.cpp文件時并不知道另一個.cpp文件的存在,也不會去查找(當遇到未決符號時它會寄希望于連接器)。這種模式在沒有模板的情況下運行良好,但遇到模板時就傻眼了,因為模板僅在需要的時候才會實例化出來,所以,當編譯器只看到模板的聲明時,它不能實例化該模板,只能創建一個具有外部連接的符號并期待連接器能夠將符號的地址決議出來。然而當實現該模板的.cpp文件中沒有用到模板的實例時,編譯器懶得去實例化,所以,整個工程的.obj中就找不到一行模板實例的二進制代碼,于是連接器也黔驢技窮了。

129、 C++中類成員的訪問權限和繼承權限問題。

一、三種訪問權限
○1public:用該關鍵字修飾的成員表示公有成員,該成員不僅可以在類內可以被 訪問,在類外也是可以被訪問的,是類對外提供的可訪問接口;
○2private:用該關鍵字修飾的成員表示私有成員,該成員僅在類內可以被訪問,在類體外是隱藏狀態;
○3protected:用該關鍵字修飾的成員表示保護成員,保護成員在類體外同樣是隱藏狀態,但是對于該類的派生類來說,相當于公有成員,在派生類中可以被訪問。
二、三種繼承方式
○1若繼承方式是public,基類成員在派生類中的訪問權限保持不變,也就是說,基類中的成員訪問權限,在派生類中仍然保持原來的訪問權限;
○2若繼承方式是private,基類所有成員在派生類中的訪問權限都會變為私有(private)權限;
○3若繼承方式是protected,基類的共有成員和保護成員在派生類中的訪問權限都會變為保護(protected)權限,私有成員在派生類中的訪問權限仍然是私有(private)權限。

130、 cout和printf有什么區別?

cout<<是一個函數,cout<<后可以跟不同的類型是因為cout<<已存在針對各種類型數據的重載,所以會自動識別數據的類型。輸出過程會首先將輸出字符放入緩沖區,然后輸出到屏幕。
cout是有緩沖輸出:cout << "abc " <<endl;或cout << "abc\n ";cout < <flush; 這兩個才是一樣的。endl相當于輸出回車后,再強迫緩沖輸出。flush立即強迫緩沖輸出。printf是無緩沖輸出。有輸出時立即輸出(lsy注:在嵌入式里盡量不用用printf打印信息,耗時!)

131、 重載運算符?

1、我們只能重載已有的運算符,而無權發明新的運算符;對于一個重載的運算符,其優先級和結合律與內置類型一致才可以;不能改變運算符操作數個數;
2、這幾種 . :: ?: sizeof typeid ** 不能重載;
3、兩種重載方式,成員運算符和非成員運算符,成員運算符比非成員運算符少一個參數;
4、下標運算符、箭頭運算符必須是成員運算符;
5、引入運算符重載,是為了實現類的多態性;
6、當重載的運算符是成員函數時,this綁定到左側運算符對象。成員運算符函數的參數數量比運算符對象的數量少一個;至少含有一個類類型的參數;
7、從參數的個數推斷到底定義的是哪種運算符,當運算符既是一元運算符又是二元運算符(+,-,*,&);
8、下標運算符必須是成員函數,下標運算符通常以所訪問元素的引用作為返回值,同時最好定義下標運算符的常量版本和非常量版本;
9、箭頭運算符必須是類的成員,解引用通常也是類的成員;重載的箭頭運算符必須返回類的指針;

132、 函數重載函數匹配原則

將函數匹配分為三個階段,確定候選函數,確定可行函數,確定最佳匹配函數。
1.確定候選函數:需要和被調用的函數同名,并且其聲明在調用點可見。
2.確定可行函數:本次調用傳入的實參能夠被候選函數使用。它要滿足兩個條件,一是形參數量和實參數量相同,二是每個實參的類型和對應形參類型相同或者能夠轉換成形參的類型。
3.尋找最佳匹配:最佳匹配最基本的思想是認為,實參類型越接近,它們就越匹配。

133、 定義和聲明的區別

1.如果是指變量的聲明和定義從編譯原理上來說,聲明是僅僅告訴編譯器,有個某類型的變量會被使用,但是編譯器并不會為它分配任何內存。而定義就是分配了內存。
2.如果是指函數的聲明和定義聲明:一般在頭文件里,對編譯器說:這里我有一個函數叫function()讓編譯器知道這個函數的存在。定義:一般在源文件里,具體就是函數的實現過程 寫明函數體。

134、 全局變量和static變量的區別

1、全局變量(外部變量)的說明之前再冠以static就構成了靜態的全局變量。全局變量本身就是靜態存儲方式,靜態全局變量當然也是靜態存儲方式。
2.這兩者在存儲方式上并無不同。這兩者的區別在于非靜態全局變量的作用域是整個源程序,當一個源程序由多個原文件組成時,非靜態的全局變量在各個源文件中都是有效的。而靜態全局變量則限制了其作用域,即只在定義該變量的源文件內有效,在同一源程序的其它源文件中不能使用它。由于靜態全局變量的作用域限于一個源文件內,只能為該源文件內的函數公用,因此可以避免在其他源文件中引起錯誤。static全局變量與普通的全局變量的區別是static全局變量只初始化一次,防止在其他文件單元被引用。

135、 static函數與普通函數有什么區別?

在函數的返回類型前加上關鍵字static,函數就被定義成為靜態函數。普通函數的定義和聲明默認情況下是extern的,但靜態函數被限定在源碼文件中,只在聲明他的文件當中可見,不能被其他文件所用。
普通函數:
static函數與普通函數有什么區別:static函數在內存中只有一份,普通函數在每個被調用中維持一份拷貝。
類成員函數:
區別1:靜態成員函數實際上是一個全局函數,不依賴一個類的對象,屬于類,不創建對象也可調用。
普通成員函數依賴一個類的對象,也就是它有一個隱藏的調用參數(this)指針,必須指向一個類的對象。
區別2:靜態函數只能訪問類中的靜態成員變量;
區別3:如果類的成員函數想作為回調函數來使用,如創建線程等,一般只能將它定義為靜態成員函數才行。
定義靜態函數有以下好處:
<1> 其他文件中可以定義相同名字的函數,不會發生沖突。
<2> 靜態函數不能被其他文件所用。

136、 靜態成員與普通成員的區別

1.生命周期
靜態成員變量從類被加載開始到類被卸載,一直存在;
普通成員變量只有在類創建對象后才開始存在,對象結束,它的生命期結束;
2.共享方式
靜態成員變量是全類共享;普通成員變量是每個對象單獨享用的;
3.定義位置
普通成員變量存儲在棧或堆中,而靜態成員變量存儲在靜態全局區;
4.初始化位置
普通成員變量在類中初始化;靜態成員變量在類外初始化;
5.默認實參
可以使用靜態成員變量作為默認實參,

137、 說一下理解 ifdef endif

1.一般情況下,源程序中所有的行都參加編譯。但是有時希望對其中一部分內容只在滿足一定條件才進行編譯,也就是對一部分內容指定編譯的條件,這就是“條件編譯”。有時,希望當滿足某條件時對一組語句進行編譯,而當條件不滿足時則編譯另一組語句。
2.條件編譯命令最常見的形式為:
#ifdef 標識符
程序段1
#else
程序段2
#endif
它的作用是:當標識符已經被定義過(一般是用#define命令定義),則對程序段1進行編譯,否則編譯程序段2。其中#else部分也可以沒有,即:#ifdef
程序段1
#denif
3.在一個大的軟件工程里面,可能會有多個文件同時包含一個頭文件,當這些文件編譯鏈接成一個可執行文件上時,就會出現大量“重定義”錯誤。在頭文件中使用#define、#ifndef、#ifdef、#endif能避免頭文件重定義。

138、 隱式轉換,如何消除隱式轉換?

1.C++的基本類型中并非完全的對立,部分數據類型之間是可以進行隱式轉換的。所謂隱式轉換,是指不需要用戶干預,編譯器私下進行的類型轉換行為。很多時候用戶可能都不知道進行了哪些轉換
2.C++面向對象的多態特性,就是通過父類的類型實現對子類的封裝。通過隱式轉換,你可以直接將一個子類的對象使用父類的類型進行返回。在比如,數值和布爾類型的轉換,整數和浮點數的轉換等。某些方面來說,隱式轉換給C++程序開發者帶來了不小的便捷。C++是一門強類型語言,類型的檢查是非常嚴格的。
3.基本數據類型,基本數據類型的轉換以取值范圍的作為轉換基礎(保證精度不丟失)。隱式轉換發生在從小->大的轉換中。比如從char轉換為int。從int->long。自定義對象 子類對象可以隱式的轉換為父類對象。
4.C++中提供了explicit關鍵字,在構造函數聲明的時候加上explicit關鍵字,能夠禁止隱式轉換。
5.如果構造函數只接受一個參數,則它實際上定義了轉換為此類類型的隱式轉換機制。可以通過將構造函數聲明為explicit加以制止隱式類型轉換,關鍵字explicit只對一個實參的構造函數有效,需要多個實參的構造函數不能用于執行隱式轉換,所以無需將這些構造函數指定為explicit。

139、 虛函數的內存結構,那菱形繼承的虛函數內存結構呢

菱形繼承的定義是:兩個子類繼承同一父類,而又有子類同時繼承這兩個子類。例如a,b兩個類同時繼承c,但是又有一個d類同時繼承a,b類。
lsy注:由于這部分內容太多,一定移步博客:(講解深入淺出,推薦!最開始不知道怎么搞了個vip可看,又取消不了,可能后續會重寫,如果你在看這篇文檔的時候發現還不能看,就聯系我)
https://blog.csdn.net/qq_41687938/article/details/120487045

140、 多繼承的優缺點,作為一個開發者怎么看待多繼承

1.C++允許為一個派生類指定多個基類,這樣的繼承結構被稱做多重繼承。
2.多重繼承的優點很明顯,就是對象可以調用多個基類中的接口;
3.如果派生類所繼承的多個基類有相同的基類,而派生類對象需要調用這個祖先類的接口方法,就會容易出現二義性
4.加上全局符確定調用哪一份拷貝。比如pa.Author::eat()調用屬于Author的拷貝。
5.使用虛擬繼承,使得多重繼承類Programmer_Author只擁有Person類的一份拷貝。

總結

以上是生活随笔為你收集整理的二十万字C/C++、嵌入式软开面试题全集宝典七的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。