二十万字C/C++、嵌入式软开面试题全集宝典八
目錄
141、 迭代器++it,it++哪個好,為什么
142、 C++如何處理多個異常的?
143、 模板和實現(xiàn)可不可以不寫在一個文件里面?為什么?
144、 在成員函數(shù)中調(diào)用delete this會出現(xiàn)什么問題?對象還可以使用嗎?
145、 三個智能指針
146、 智能指針怎么用?智能指針出現(xiàn)循環(huán)引用怎么解決?
147、 智能指針的作用
148、 auto_ptr作用
149、 class、union、struct的區(qū)別
150、 動態(tài)聯(lián)編與靜態(tài)聯(lián)編
151、 動態(tài)編譯與靜態(tài)編譯
152、 動態(tài)鏈接和靜態(tài)鏈接區(qū)別
153、 在不使用額外空間的情況下,交換兩個數(shù)?
154、 strcpy和memcpy的區(qū)別
155、 簡述strcpy、sprintf與memcpy的區(qū)別
156、 strcpy函數(shù)和strncpy函數(shù)的區(qū)別?哪個函數(shù)更安全?
157、 執(zhí)行int main(int argc, char *argv[])時的內(nèi)存結(jié)構(gòu)
158、 volatile關(guān)鍵字的作用?
159、 講講大端小端,如何檢測(三種方法)
160、 查看內(nèi)存的方法
?
141、 迭代器++it,it++哪個好,為什么
1.前置返回一個引用,后置返回一個對象
// ++i實現(xiàn)代碼為: int& operator++() { *this += 1; return *this; }
2.前置不會產(chǎn)生臨時對象,后置必須產(chǎn)生臨時對象,臨時對象會導致效率降低
?
142、 C++如何處理多個異常的?
1.C++中的異常情況:
○1語法錯誤(編譯錯誤):比如變量未定義、括號不匹配、關(guān)鍵字拼寫錯誤等等編譯器在編譯時能發(fā)現(xiàn)的錯誤,這類錯誤可以及時被編譯器發(fā)現(xiàn),而且可以及時知道出錯的位置及原因,方便改正。
○2運行時錯誤:比如數(shù)組下標越界、系統(tǒng)內(nèi)存不足等等。這類錯誤不易被程序員發(fā)現(xiàn),它能通過編譯且能進入運行,但運行時會出錯,導致程序崩潰。為了有效處理程序運行時錯誤,C++中引入異常處理機制來解決此問題。
2.C++異常處理機制:
異常處理基本思想:執(zhí)行一個函數(shù)的過程中發(fā)現(xiàn)異常,可以不用在本函數(shù)內(nèi)立即進行處理,而是拋出該異常,讓函數(shù)的調(diào)用者直接或間接處理這個問題。
C++異常處理機制由3個模塊組成:try(檢查)、throw(拋出)、catch(捕獲)
拋出異常的語句格式為:throw 表達式;如果try塊中程序段發(fā)現(xiàn)了異常則拋出異常。
try{可能拋出異常的語句;(檢查)}
catch(類型名[形參名])//捕獲特定類型的異常
{//處理1; }
catch(類型名[形參名])//捕獲特定類型的異常
{//處理2; }
catch(…)//捕獲所有類型的異常{}
143、 模板和實現(xiàn)可不可以不寫在一個文件里面?為什么?
不可以!因為在編譯時模板并不能生成真正的二進制代碼,而是在編譯調(diào)用模板類或函數(shù)的CPP文件時才會去找對應(yīng)的模板聲明和實現(xiàn),在這種情況下編譯器是不知道實現(xiàn)模板類或函數(shù)的CPP文件的存在,所以它只能找到模板類或函數(shù)的聲明而找不到實現(xiàn),而只好創(chuàng)建一個符號寄希望于鏈接程序找地址。但模板類或函數(shù)的實現(xiàn)并不能被編譯成二進制代碼,結(jié)果鏈接程序找不到地址只好報錯了。
《C++編程思想》第15章(第300頁)說明了原因:模板定義很特殊。由template<…>處理的任何東西都意味著編譯器在當時不為它分配存儲空間,它一直處于等待狀態(tài)直到被一個模板實例告知。在編譯器和連接器的某一處,有一機制能去掉指定模板的多重定義。所以為了容易使用,幾乎總是在頭文件中放置全部的模板聲明和定義。
144、 在成員函數(shù)中調(diào)用delete this會出現(xiàn)什么問題?對象還可以使用嗎?
1.類對象空間
在類對象的內(nèi)存空間中,只有數(shù)據(jù)成員和虛函數(shù)表指針,并不包含代碼內(nèi)容,類的成員函數(shù)單獨放在代碼段中。在調(diào)用成員函數(shù)時,隱含傳遞一個this指針,讓成員函數(shù)知道當前是哪個對象在調(diào)用它。當調(diào)用delete this時,類對象的內(nèi)存空間被釋放。在delete this之后進行的其他任何函數(shù)調(diào)用,只要不涉及到this指針的內(nèi)容,都能夠正常運行。一旦涉及到this指針,如操作數(shù)據(jù)成員,調(diào)用虛函數(shù)等,就會出現(xiàn)不可預期的問題。
2.為什么是不可預期的問題?
delete this之后不是釋放了類對象的內(nèi)存空間了么,那么這段內(nèi)存應(yīng)該已經(jīng)還給系統(tǒng),不再屬于這個進程。照這個邏輯來看,應(yīng)該發(fā)生指針錯誤,無訪問權(quán)限之類的令系統(tǒng)崩潰的問題才對啊?這個問題牽涉到操作系統(tǒng)的內(nèi)存管理策略。delete this釋放了類對象的內(nèi)存空間,但是內(nèi)存空間卻并不是馬上被回收到系統(tǒng)中,可能是緩沖或者其他什么原因,導致這段內(nèi)存空間暫時并沒有被系統(tǒng)收回。此時這段內(nèi)存是可以訪問的,你可以加上100,加上200,但是其中的值卻是不確定的。當你獲取數(shù)據(jù)成員,可能得到的是一串很長的未初始化的隨機數(shù);訪問虛函數(shù)表,指針無效的可能性非常高,造成系統(tǒng)崩潰。
3.如果在類的析構(gòu)函數(shù)中調(diào)用delete this,會發(fā)生什么?
會導致堆棧溢出。原因很簡單,delete的本質(zhì)是“為將被釋放的內(nèi)存調(diào)用一個或多個析構(gòu)函數(shù),然后,釋放內(nèi)存”。顯然,delete this會去調(diào)用本對象的析構(gòu)函數(shù),而析構(gòu)函數(shù)中又調(diào)用delete this,形成無限遞歸,造成堆棧溢出,系統(tǒng)崩潰。(值傳遞的拷貝構(gòu)造函數(shù)也是無限遞歸)
145、 三個智能指針
1.shared_ptr共享的智能指針:
shared_ptr使用引用計數(shù),每一個shared_ptr的拷貝都指向相同的內(nèi)存。在最后一個shared_ptr析構(gòu)的時候,內(nèi)存才會被釋放。
注意事項:
○1不要用一個原始指針初始化多個shared_ptr。
○2不要再函數(shù)實參中創(chuàng)建shared_ptr,在調(diào)用函數(shù)之前先定義以及初始化它。
○3不要將this指針作為shared_ptr返回出來。
○4要避免循環(huán)引用。(兩個類,互相包含對方。使用weak_ptr解決)
2.unique_ptr獨占的智能指針:
<1>unique_ptr是一個獨占的智能指針,他不允許其他的智能指針共享其內(nèi)部的指針,不允許通過賦值將一個unique_ptr賦值給另外一個unique_ptr。
<2>unique_ptr不允許復制,但可以通過函數(shù)返回給其他的unique_ptr,還可以通過std::move來轉(zhuǎn)移到其他的unique_ptr,這樣它本身就不再擁有原來指針的所有權(quán)了。
<3>如果希望只有一個智能指針管理資源或管理數(shù)組就用unique_ptr,如果希望多個智能指針管理同一個資源就用shared_ptr。
3.weak_ptr弱引用的智能指針:
弱引用的智能指針weak_ptr是用來監(jiān)視shared_ptr的,不會使引用計數(shù)加一,它不管理shared_ptr內(nèi)部的指針,主要是為了監(jiān)視shared_ptr的生命周期,更像是shared_ptr的一個助手。weak_ptr沒有重載運算符*和->,因為它不共享指針,不能操作資源,主要是為了通過shared_ptr獲得資源的監(jiān)測權(quán),它的構(gòu)造不會增加引用計數(shù),它的析構(gòu)不會減少引用計數(shù),純粹只是作為一個旁觀者來監(jiān)視shared_ptr中關(guān)連的資源是否存在。 weak_ptr還可以用來返回this指針和解決循環(huán)引用的問題。
146、 智能指針怎么用?智能指針出現(xiàn)循環(huán)引用怎么解決?
1.shared_ptr
調(diào)用一個名為make_shared的標準庫函數(shù),
shared_ptr<int> p = make_shared<int>(42);
通常用auto更方便,auto p = …;shared_ptr<int> p2(new int(2));
每個shared_ptr都有一個關(guān)聯(lián)的計數(shù)器,通常稱為引用計數(shù),一旦一個shared_ptr的計數(shù)器變?yōu)?,它就會自動釋放自己所管理的對象;shared_ptr的析構(gòu)函數(shù)就會遞減它所指的對象的引用計數(shù)。如果引用計數(shù)變?yōu)?,shared_ptr的析構(gòu)函數(shù)就會銷毀對象,并釋放它占用的內(nèi)存。
2.unique_ptr
一個unique_ptr擁有它所指向的對象。某個時刻只能有一個unique_ptr指向一個給定對象。當unique_ptr被銷毀時,它所指向的對象也被銷毀。
3.weak_ptr
weak_ptr是一種不控制所指向?qū)ο笊嫫诘闹悄苤羔?#xff0c;它指向由一個shared_ptr管理的對象,將一個weak_ptr綁定到一個shared_ptr不會改變引用計數(shù),一旦最后一個指向?qū)ο蟮膕hared_ptr被銷毀,對象就會被釋放,即使有weak_ptr指向?qū)ο?#xff0c;對象還是會被釋放。
弱指針用于專門解決shared_ptr循環(huán)引用的問題,weak_ptr不會修改引用計數(shù),即其存在與否并不影響對象的引用計數(shù)器。循環(huán)引用就是:兩個對象互相使用一個shared_ptr成員變量指向?qū)Ψ健H跻貌⒉粚ο蟮膬?nèi)存進行管理,在功能上類似于普通指針,然而一個比較大的區(qū)別是,弱引用能檢測到所管理的對象是否已經(jīng)被釋放,從而避免訪問非法內(nèi)存。
5.循環(huán)引用問題
雖然智能指針會減少內(nèi)存泄漏的可能性,但是如果使用智能指針的方式不對,一樣會造成內(nèi)存泄漏。比較典型的情況是循環(huán)引用問題,比如這段代碼:
這個程序中智能指針的引用情況如下圖
上圖中,class A和class B的對象各自被兩個智能指針管理,也就是A object和B object引用計數(shù)都為2,為什么是2?
分析class A對象的引用情況,該對象被main函數(shù)中的pa和class B對象中的ptr管理,因此A object引用計數(shù)是2,B object同理。
在這種情況下,在main函數(shù)中一個while循環(huán)結(jié)束的時候,pa和pb的析構(gòu)函數(shù)被調(diào)用,但是class A對象和class B對象仍然被一個智能指針管理,A object和B object引用計數(shù)變成1,于是這兩個對象的內(nèi)存無法被釋放,造成內(nèi)存泄漏,如下圖所示
解決方法
解決方法很簡單,把class A或者class B中的shared_ptr改成weak_ptr即可,由于weak_ptr不會增加shared_ptr的引用計數(shù),所以A object和B object中有一個的引用計數(shù)為1,在pa和pb析構(gòu)時,會正確地釋放掉內(nèi)存。
147、 智能指針的作用
1.C++11中引入了智能指針的概念,方便管理堆內(nèi)存。使用普通指針,容易造成堆內(nèi)存泄露(忘記釋放),二次釋放,程序發(fā)生異常時內(nèi)存泄露等問題等,使用智能指針能更好的管理堆內(nèi)存。
2.智能指針在C++11版本之后提供,包含在頭文件<memory>中,shared_ptr、unique_ptr、weak_ptr。shared_ptr多個指針指向相同的對象。shared_ptr使用引用計數(shù),每一個shared_ptr的拷貝都指向相同的內(nèi)存。每使用他一次,內(nèi)部的引用計數(shù)加1,每析構(gòu)一次,內(nèi)部的引用計數(shù)減1,減為0時,自動刪除所指向的堆內(nèi)存。shared_ptr內(nèi)部的引用計數(shù)是線程安全的,但是對象的讀取需要加鎖。
3.初始化。智能指針是個模板類,可以指定類型,傳入指針通過構(gòu)造函數(shù)初始化。也可以使用make_shared函數(shù)初始化。不能將指針直接賦值給一個智能指針,一個是類,一個是指針。例如std::shared_ptr<int> p4 = new int(1);的寫法是錯誤的
4.拷貝和賦值。拷貝使得對象的引用計數(shù)增加1,賦值使得原對象引用計數(shù)減1,當計數(shù)為0時,自動釋放內(nèi)存。后來指向的對象引用計數(shù)加1,指向后來的對象
5.unique_ptr“唯一”擁有其所指對象,同一時刻只能有一個unique_ptr指向給定對象(通過禁止拷貝語義、只有移動語義來實現(xiàn))。相比與原始指針unique_ptr用于其RAII的特性,使得在出現(xiàn)異常的情況下,動態(tài)資源能得到釋放。unique_ptr指針本身的生命周期:從unique_ptr指針創(chuàng)建時開始,直到離開作用域。離開作用域時,若其指向?qū)ο?#xff0c;則將其所指對象銷毀(默認使用delete操作符,用戶可指定其他操作)。unique_ptr指針與其所指對象的關(guān)系:在智能指針生命周期內(nèi),可以改變智能指針所指對象,如創(chuàng)建智能指針時通過構(gòu)造函數(shù)指定、通過reset方法重新指定、通過release方法釋放所有權(quán)、通過移動語義轉(zhuǎn)移所有權(quán)。
6.智能指針類將一個計數(shù)器與類指向的對象相關(guān)聯(lián),引用計數(shù)跟蹤該類有多少個對象共享同一指針。每次創(chuàng)建類的新對象時,初始化指針并將引用計數(shù)置為1;當對象作為另一對象的副本而創(chuàng)建時,拷貝構(gòu)造函數(shù)拷貝指針并增加與之相應(yīng)的引用計數(shù);對一個對象進行賦值時,賦值操作符減少左操作數(shù)所指對象的引用計數(shù)(如果引用計數(shù)為減至0,則刪除對象),并增加右操作數(shù)所指對象的引用計數(shù);調(diào)用析構(gòu)函數(shù)時,構(gòu)造函數(shù)減少引用計數(shù)(如果引用計數(shù)減至0,則刪除基礎(chǔ)對象)。
7.weak_ptr 是一種不控制對象生命周期的智能指針, 它指向一個 shared_ptr 管理的對象. 進行該對象的內(nèi)存管理的是那個強引用的 shared_ptr. weak_ptr只是提供了對管理對象的一個訪問手段。weak_ptr 設(shè)計的目的是為配合 shared_ptr 而引入的一種智能指針來協(xié)助 shared_ptr 工作, 它只可以從一個 shared_ptr 或另一個 weak_ptr 對象構(gòu)造, 它的構(gòu)造和析構(gòu)不會引起引用記數(shù)的增加或減少。
148、 auto_ptr作用
1.auto_ptr的出現(xiàn),主要是為了解決“有異常拋出時發(fā)生內(nèi)存泄漏”的問題;拋出異常,將導致指針p所指向的空間得不到釋放而導致內(nèi)存泄漏;
2.auto_ptr構(gòu)造時取得某個對象的控制權(quán),在析構(gòu)時釋放該對象。我們實際上是創(chuàng)建一個auto_ptr<Type>類型的局部對象,該局部對象析構(gòu)時,會將自身所擁有的指針空間釋放,所以不會有內(nèi)存泄漏;
3.auto_ptr的構(gòu)造函數(shù)是explicit,阻止了一般指針隱式轉(zhuǎn)換為 auto_ptr的構(gòu)造,所以不能直接將一般類型的指針賦值給auto_ptr類型的對象,必須用auto_ptr的構(gòu)造函數(shù)創(chuàng)建對象;
4.由于auto_ptr對象析構(gòu)時會刪除它所擁有的指針,所以使用時避免多個auto_ptr對象管理同一個指針;
5.Auto_ptr內(nèi)部實現(xiàn),析構(gòu)函數(shù)中刪除對象用的是delete而不是delete[],所以auto_ptr不能管理數(shù)組;
6.auto_ptr支持所擁有的指針類型之間的隱式類型轉(zhuǎn)換。
7.可以通過*和->運算符對auto_ptr所有用的指針進行提領(lǐng)操作;
8.T* get(),獲得auto_ptr所擁有的指針;T* release(),釋放auto_ptr的所有權(quán),并將所有用的指針返回。
149、 class、union、struct的區(qū)別
1.C語言中,struct只是一個聚合數(shù)據(jù)類型,沒有權(quán)限設(shè)置,無法添加成員函數(shù),無法實現(xiàn)面向?qū)ο缶幊?#xff0c;且如果沒有typedef結(jié)構(gòu)名,聲明結(jié)構(gòu)變量必須添加關(guān)鍵字struct。
2.C++中,struct功能大大擴展,可以有權(quán)限設(shè)置(默認權(quán)限為public),可以像class一樣有成員函數(shù),繼承(默認public繼承),可以實現(xiàn)面對對象編程,允許在聲明結(jié)構(gòu)變量時省略關(guān)鍵字struct。
3.C與C++中的union:一種數(shù)據(jù)格式,能夠存儲不同的數(shù)據(jù)類型,但只能同時存儲其中的一種類型。C++ union結(jié)構(gòu)式一種特殊的類。它能夠包含訪問權(quán)限、成員變量、成員函數(shù)(可以包含構(gòu)造函數(shù)和析構(gòu)函數(shù))。它不能包含虛函數(shù)和靜態(tài)數(shù)據(jù)變量。它也不能被用作其他類的基類,它本身也不能有從某個基類派生而來。Union中得默認訪問權(quán)限是public。union類型是共享內(nèi)存的,以size最大的結(jié)構(gòu)作為自己的大小。每個數(shù)據(jù)成員在內(nèi)存中的起始地址是相同的。
4.在C/C++程序的編寫中,當多個基本數(shù)據(jù)類型或復合數(shù)據(jù)結(jié)構(gòu)要占用同一片內(nèi)存時,我們要使用聯(lián)合體;當多種類型,多個對象,多個事物只取其一時(我們姑且通俗地稱其為“n 選1”),我們也可以使用聯(lián)合體來發(fā)揮其長處。在某一時刻,一個union中只能有一個值是有效的。union的一個用法就是可以用來測試CPU是大端模式還是小端模式。
150、 動態(tài)聯(lián)編與靜態(tài)聯(lián)編
1.在C++中,聯(lián)編是指一個計算機程序的不同部分彼此關(guān)聯(lián)的過程。按照聯(lián)編所進行的階段不同,可以分為靜態(tài)聯(lián)編和動態(tài)聯(lián)編;
2.靜態(tài)聯(lián)編是指聯(lián)編工作在編譯階段完成的,這種聯(lián)編過程是在程序運行之前完成的,又稱為早期聯(lián)編。要實現(xiàn)靜態(tài)聯(lián)編,在編譯階段就必須確定程序中的操作調(diào)用(如函數(shù)調(diào)用)與執(zhí)行該操作代碼間的關(guān)系,確定這種關(guān)系稱為束定,在編譯時的束定稱為靜態(tài)束定。靜態(tài)聯(lián)編對函數(shù)的選擇是基于指向?qū)ο蟮闹羔樆蛘咭玫念愋?。其?yōu)點是效率高,但靈活性差。
3.動態(tài)聯(lián)編是指聯(lián)編在程序運行時動態(tài)地進行,根據(jù)當時的情況來確定調(diào)用哪個同名函數(shù),實際上是在運行時虛函數(shù)的實現(xiàn)。這種聯(lián)編又稱為晚期聯(lián)編,或動態(tài)束定。動態(tài)聯(lián)編對成員函數(shù)的選擇是基于對象的類型,針對不同的對象類型將做出不同的編譯結(jié)果。C++中一般情況下的聯(lián)編是靜態(tài)聯(lián)編,但是當涉及到多態(tài)性和虛函數(shù)時應(yīng)該使用動態(tài)聯(lián)編。動態(tài)聯(lián)編的優(yōu)點是靈活性強,但效率低。動態(tài)聯(lián)編規(guī)定,只能通過指向基類的指針或基類對象的引用來調(diào)用虛函數(shù),其格式為:指向基類的指針變量名->虛函數(shù)名(實參表)或基類對象的引用名.虛函數(shù)名(實參表)
4.實現(xiàn)動態(tài)聯(lián)編三個條件:
必須把動態(tài)聯(lián)編的行為定義為類的虛函數(shù);
類之間應(yīng)滿足子類型關(guān)系,通常表現(xiàn)為一個類從另一個類公有派生而來;
必須先使用基類指針指向子類型的對象,然后直接或間接使用基類指針調(diào)用虛函數(shù);
151、 動態(tài)編譯與靜態(tài)編譯
1.靜態(tài)編譯,編譯器在編譯可執(zhí)行文件時,把需要用到的對應(yīng)動態(tài)鏈接庫中的部分提取出來,連接到可執(zhí)行文件中去,使可執(zhí)行文件在運行時不需要依賴于動態(tài)鏈接庫;
2.動態(tài)編譯的可執(zhí)行文件需要附帶一個動態(tài)鏈接庫,在執(zhí)行時,需要調(diào)用其對應(yīng)動態(tài)鏈接庫的命令。所以其優(yōu)點一方面是縮小了執(zhí)行文件本身的體積,另一方面是加快了編譯速度,節(jié)省了系統(tǒng)資源。缺點是哪怕是很簡單的程序,只用到了鏈接庫的一兩條命令,也需要附帶一個相對龐大的鏈接庫;二是如果其他計算機上沒有安裝對應(yīng)的運行庫,則用動態(tài)編譯的可執(zhí)行文件就不能運行。
152、 動態(tài)鏈接和靜態(tài)鏈接區(qū)別
1.靜態(tài)連接庫就是把(lib)文件中用到的函數(shù)代碼直接鏈接進目標程序,程序運行的時候不再需要其它的庫文件;動態(tài)鏈接就是把調(diào)用的函數(shù)所在文件模塊(DLL)和調(diào)用函數(shù)在文件中的位置等信息鏈接進目標程序,程序運行的時候再從DLL中尋找相應(yīng)函數(shù)代碼,因此需要相應(yīng)DLL文件的支持。
2.靜態(tài)鏈接庫與動態(tài)鏈接庫都是共享代碼的方式,如果采用靜態(tài)鏈接庫,則無論你愿不愿意,lib 中的指令都全部被直接包含在最終生成的 EXE 文件中了。但是若使用 DLL,該 DLL 不必被包含在最終 EXE 文件中,EXE 文件執(zhí)行時可以“動態(tài)”地引用和卸載這個與 EXE 獨立的 DLL 文件。靜態(tài)鏈接庫和動態(tài)鏈接庫的另外一個區(qū)別在于靜態(tài)鏈接庫中不能再包含其他的動態(tài)鏈接庫或者靜態(tài)庫,而在動態(tài)鏈接庫中還可以再包含其他的動態(tài)或靜態(tài)鏈接庫。
3.動態(tài)庫就是在需要調(diào)用其中的函數(shù)時,根據(jù)函數(shù)映射表找到該函數(shù)然后調(diào)入堆棧執(zhí)行。如果在當前工程中有多處對dll文件中同一個函數(shù)的調(diào)用,那么執(zhí)行時,這個函數(shù)只會留下一份拷貝。但是如果有多處對lib文件中同一個函數(shù)的調(diào)用,那么執(zhí)行時,該函數(shù)將在當前程序的執(zhí)行空間里留下多份拷貝,而且是一處調(diào)用就產(chǎn)生一份拷貝。
153、 在不使用額外空間的情況下,交換兩個數(shù)?
1.算術(shù)
x = x + y; y = x - y; x = x - y;2.異或
x = x^y;// 只能對int,char.. y = x^y; x = x^y; x ^= y ^= x;154、 strcpy和memcpy的區(qū)別
1、復制的內(nèi)容不同。strcpy只能復制字符串,而memcpy可以復制任意內(nèi)容,例如字符數(shù)組、整型、結(jié)構(gòu)體、類等。
2、復制的方法不同。strcpy不需要指定長度,它遇到被復制字符的串結(jié)束符"\0"才結(jié)束,所以容易溢出。memcpy則是根據(jù)其第3個參數(shù)決定復制的長度。
3、用途不同。通常在復制字符串時用strcpy,而需要復制其他類型數(shù)據(jù)時則一般用memcpy。
155、 簡述strcpy、sprintf與memcpy的區(qū)別
1.操作對象不同
○1strcpy的兩個操作對象均為字符串
○2sprintf的操作源對象可以是多種數(shù)據(jù)類型,目的操作對象是字符串
○3memcpy的兩個對象就是兩個任意可操作的內(nèi)存地址,并不限于何種數(shù)據(jù)類型。
2.執(zhí)行效率不同
memcpy最高,strcpy次之,sprintf的效率最低。
3.實現(xiàn)功能不同
○1strcpy主要實現(xiàn)字符串變量間的拷貝
○2sprintf主要實現(xiàn)其他數(shù)據(jù)類型格式到字符串的轉(zhuǎn)化
○3memcpy主要是內(nèi)存塊間的拷貝。
156、 strcpy函數(shù)和strncpy函數(shù)的區(qū)別?哪個函數(shù)更安全?
1.函數(shù)原型
char* strcpy(char* strDest, const char* strSrc) char* strncpy(char* strDest, const char* strSrc, int pos)2.strcpy函數(shù): 如果參數(shù) dest 所指的內(nèi)存空間不夠大,可能會造成緩沖溢出(buffer Overflow)的錯誤情況,在編寫程序時請?zhí)貏e留意,或者用strncpy()來取代。
strncpy函數(shù):用來復制源字符串的前n個字符,src 和 dest 所指的內(nèi)存區(qū)域不能重疊,且 dest 必須有足夠的空間放置n個字符。
3.如果目標長>指定長>源長,則將源長全部拷貝到目標長,自動加上’\0’如果指定長<源長,則將源長中按指定長度拷貝到目標字符串,不包括’\0’如果指定長>目標長,運行時錯誤;
157、 執(zhí)行int main(int argc, char *argv[])時的內(nèi)存結(jié)構(gòu)
參數(shù)的含義是程序在命令行下運行的時候,需要輸入argc 個參數(shù),每個參數(shù)是以char 類型輸入的,依次存在數(shù)組里面,數(shù)組是 argv[],所有的參數(shù)在指針
char * 指向的內(nèi)存中,數(shù)組的中元素的個數(shù)為 argc 個,第一個參數(shù)為程序的名稱(gcc時能夠體現(xiàn))。
158、 volatile關(guān)鍵字的作用?
volatile關(guān)鍵字是一種類型修飾符,用它聲明的類型變量表示可以被某些編譯器未知的因素更改,比如:操作系統(tǒng)、硬件或者其它線程等。遇到這個關(guān)鍵字聲明的變量,編譯器對訪問該變量的代碼就不再進行優(yōu)化,從而可以提供對特殊地址的穩(wěn)定訪問。聲明時語法:int volatile vInt;當要求使用 volatile 聲明的變量的值的時候,系統(tǒng)總是重新從它所在的內(nèi)存讀取數(shù)據(jù),即使它前面的指令剛剛從該處讀取過數(shù)據(jù)。而且讀取的數(shù)據(jù)立刻被保存。
1、性質(zhì):
易變性:在匯編層?反映出來,就是兩條語句,下?條語句不會直接使?上?條語句對應(yīng)的volatile 變量的寄存器內(nèi)容,?是重新從內(nèi)存中讀取。
不可優(yōu)化性: volatile 告訴編譯器,不要對我這個變量進?各種激進的優(yōu)化,甚?將變量直接消除,保證程序員寫在代碼中的指令,?定會被執(zhí)?
順序性:能夠保證 volatile 變量之間的順序性,編譯器不會進?亂序優(yōu)化。
2、應(yīng)用場景:
1) 中斷服務(wù)程序中修改的供其它程序檢測的變量需要加volatile;
2) 多任務(wù)環(huán)境下各任務(wù)間共享的標志應(yīng)該加volatile;
3) 存儲器映射的硬件寄存器通常也要加volatile說明,因為每次對它的讀寫都可能由不同意義;
159、 講講大端小端,如何檢測(三種方法)
大端模式:是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的低地址中,而數(shù)據(jù)的低字節(jié)保存在內(nèi)存的高地址端。
小端模式,是指數(shù)據(jù)的高字節(jié)保存在內(nèi)存的高地址中,低位字節(jié)保存在在內(nèi)存的低地址端。
1.直接讀取存放在內(nèi)存中的十六進制數(shù)值,取低位進行值判斷
2.用共同體來進行判斷
union共同體所有數(shù)據(jù)成員是共享一段內(nèi)存的,后寫入的成員數(shù)據(jù)將覆蓋之前的成員數(shù)據(jù),成員數(shù)據(jù)都有相同的首地址。Union的大小為最大數(shù)據(jù)成員的大小。
union的成員數(shù)據(jù)共用內(nèi)存,并且首地址都是低地址首字節(jié)。int i= 1時:大端存儲1放在最高位,小端存儲1放在最低位。當讀取char ch時,是最低地址首字節(jié),大小端會顯示不同的值。
160、 查看內(nèi)存的方法
1.首先打開vs編譯器,創(chuàng)建好項目,并且將代碼寫進去,這里就不貼代碼了,你可以隨便的寫個做個測試;
2.調(diào)試的時候做好相應(yīng)的斷點,然后點擊開始調(diào)試;
2.1程序調(diào)試之后會在你設(shè)置斷點的地方暫停,然后選擇調(diào)試->窗口->內(nèi)存,就打開了內(nèi)存數(shù)據(jù)查看的窗口了。
總結(jié)
以上是生活随笔為你收集整理的二十万字C/C++、嵌入式软开面试题全集宝典八的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 双目估计方法_教你提高双目立体视觉系统的
- 下一篇: 二十万字C/C++、嵌入式软开面试题全集