C/C++经典面试题
面試題1:變量的聲明和定義有什么區(qū)別
為變量分配地址和存儲(chǔ)空間的稱為定義,不分配地址的稱為聲明。一個(gè)變量可以在多個(gè)地方聲明,但只能在一個(gè)地方定義。加入extern修飾的是變量的聲明,說明此變量將在文件以外或在文件后面部分定義。
說明:很多時(shí)候一個(gè)變量,只是聲明,不分配內(nèi)存空間,知道具體使用時(shí)才初始化,分配內(nèi)存空間,如外部變量。
面試題2:sizeof和strlen的區(qū)別
sizeof和strlen有以下區(qū)別:
? sizeof是一個(gè)操作符,strlen是庫函數(shù)。
? sizeof的參數(shù)可以是數(shù)據(jù)的類型,也可以是變量,而strlen只能以結(jié)尾為‘\0‘的字符串作參數(shù)。
? 編譯器在編譯時(shí)就計(jì)算出了sizeof的結(jié)果。而strlen函數(shù)必須在運(yùn)行時(shí)才能計(jì)算出來。并且sizeof計(jì)算的是數(shù)據(jù)類型占內(nèi)存的大小,而strlen計(jì)算的是字符串實(shí)際的長度。
? 數(shù)組做sizeof的參數(shù)不退化,傳遞給strlen就退化為指針了。
注意:有些是操作符看起來像是函數(shù),而有些函數(shù)名看起來又像操作符,這類容易混淆的名稱一定要加以區(qū)分,否則遇到數(shù)組名這類特殊數(shù)據(jù)類型作參數(shù)時(shí)就很容易出錯(cuò)。最容易混淆為函數(shù)的操作符就是sizeof。
說明:指針是一種普通的變量,從訪問上沒有什么不同于其他變量的特性。其保存的數(shù)值是個(gè)整型數(shù)據(jù),和整型變量不同的是,這個(gè)整型數(shù)據(jù)指向的是一段內(nèi)存地址。
面試題3:寫一個(gè)“標(biāo)準(zhǔn)”宏MIN
#define min(a,b) ((a)<=(b)?(a):(b))
面試題4:一個(gè)指針可以是volatile嗎?
可以,因?yàn)橹羔樅推胀ㄗ兞恳粯?#xff0c;有時(shí)也有變化程序的不可控性。常見例:子中斷服務(wù)子程序修改一個(gè)指向一個(gè)buffer的指針時(shí),必須用volatile來修飾這個(gè)指針。
面試題5:a 和 &a 有什么區(qū)別
請寫出以下代碼的打印結(jié)果,主要目的是考察a和&a的區(qū)別。
[cpp]?view plaincopy
輸出結(jié)果:2,5。
注意:數(shù)組名a可以作數(shù)組的首地址,而&a是數(shù)組的指針。思考,將原式的int *ptr=(int *)(&a+1);改為int *ptr=(int *)(a+1);時(shí)輸出結(jié)果將是什么呢?
面試題6:簡述C、C++程序編譯的內(nèi)存分配情況
C、C++中內(nèi)存分配方式可以分為三種:
(1)從靜態(tài)存儲(chǔ)區(qū)域分配:
內(nèi)存在程序編譯時(shí)就已經(jīng)分配好,這塊內(nèi)存在程序的整個(gè)運(yùn)行期間都存在。速度快、不容易出錯(cuò),因?yàn)橛邢到y(tǒng)會(huì)善后。例如全局變量,static變量等。
(2)在棧上分配:
在執(zhí)行函數(shù)時(shí),函數(shù)內(nèi)局部變量的存儲(chǔ)單元都在棧上創(chuàng)建,函數(shù)執(zhí)行結(jié)束時(shí)這些存儲(chǔ)單元自動(dòng)被釋放。棧內(nèi)存分配運(yùn)算內(nèi)置于處理器的指令集中,效率很高,但是分配的內(nèi)存容量有限。
(3)從堆上分配:
即動(dòng)態(tài)內(nèi)存分配。程序在運(yùn)行的時(shí)候用malloc或new申請任意大小的內(nèi)存,程序員自己負(fù)責(zé)在何時(shí)用free或delete釋放內(nèi)存。動(dòng)態(tài)內(nèi)存的生存期由程序員決定,使用非常靈活。如果在堆上分配了空間,就有責(zé)任回收它,否則運(yùn)行的程序會(huì)出現(xiàn)內(nèi)存泄漏,另外頻繁地分配和釋放不同大小的堆空間將會(huì)產(chǎn)生堆內(nèi)碎塊。
一個(gè)C、C++程序編譯時(shí)內(nèi)存分為5大存儲(chǔ)區(qū):堆區(qū)、棧區(qū)、全局區(qū)、文字常量區(qū)、程序代碼區(qū)。
面試題7:簡述strcpy sprintf與mencpy的區(qū)別
三者主要有以下不同之處:
(1)操作對象不同,strcpy的兩個(gè)操作對象均為字符串,sprintf的操作源對象可以是多種數(shù)據(jù)類型,目的操作對象是字符串,memcpy 的兩個(gè)對象就是兩個(gè)任意可操作的內(nèi)存地址,并不限于何種數(shù)據(jù)類型。
(2)執(zhí)行效率不同,memcpy最高,strcpy次之,sprintf的效率最低。
(3)實(shí)現(xiàn)功能不同,strcpy主要實(shí)現(xiàn)字符串變量間的拷貝,sprintf主要實(shí)現(xiàn)其他數(shù)據(jù)類型格式到字符串的轉(zhuǎn)化,memcpy主要是內(nèi)存塊間的拷貝。
說明:strcpy、sprintf與memcpy都可以實(shí)現(xiàn)拷貝的功能,但是針對的對象不同,根據(jù)實(shí)際需求,來選擇合適的函數(shù)實(shí)現(xiàn)拷貝功能。
面試題8:鏈表與數(shù)組的區(qū)別
數(shù)組和鏈表有以下幾點(diǎn)不同:
(1)存儲(chǔ)形式:數(shù)組是一塊連續(xù)的空間,聲明時(shí)就要確定長度。鏈表是一塊可不連續(xù)的動(dòng)態(tài)空間,長度可變,每個(gè)結(jié)點(diǎn)要保存相鄰結(jié)點(diǎn)指針。
(2)數(shù)據(jù)查找:數(shù)組的線性查找速度快,查找操作直接使用偏移地址。鏈表需要按順序檢索結(jié)點(diǎn),效率低。
(3)數(shù)據(jù)插入或刪除:鏈表可以快速插入和刪除結(jié)點(diǎn),而數(shù)組則可能需要大量數(shù)據(jù)移動(dòng)。
(4)越界問題:鏈表不存在越界問題,數(shù)組有越界問題。
說明:在選擇數(shù)組或鏈表數(shù)據(jù)結(jié)構(gòu)時(shí),一定要根據(jù)實(shí)際需要進(jìn)行選擇。數(shù)組便于查詢,鏈表便于插入刪除。數(shù)組節(jié)省空間但是長度固定,鏈表雖然變長但是占了更多的存儲(chǔ)空間。
面試題9:簡述隊(duì)列和棧的異同
隊(duì)列和棧都是線性存儲(chǔ)結(jié)構(gòu),但是兩者的插入和刪除數(shù)據(jù)的操作不同,隊(duì)列是“先進(jìn)先出”,棧是“后進(jìn)先出”。
注意:區(qū)別棧區(qū)和堆區(qū)。堆區(qū)的存取是“順序隨意”,而棧區(qū)是“后進(jìn)先出”。棧由編譯器自動(dòng)分配釋放 ,存放函數(shù)的參數(shù)值,局部變量的值等。其操作方式類似于數(shù)據(jù)結(jié)構(gòu)中的棧。堆一般由程序員分配釋放, 若程序員不釋放,程序結(jié)束時(shí)可能由OS回收。分配方式類似于鏈表。
它與本題中的堆和棧是兩回事。堆棧只是一種數(shù)據(jù)結(jié)構(gòu),而堆區(qū)和棧區(qū)是程序的不同內(nèi)存存儲(chǔ)區(qū)域。
面試題10:編碼實(shí)現(xiàn)直接插入排序
直接插入排序編程實(shí)現(xiàn)如下:
[cpp]?view plaincopy
面試題11:編碼實(shí)現(xiàn)冒泡排序
冒泡排序編程實(shí)現(xiàn)如下:
[cpp]?view plaincopy
面試題12:編碼實(shí)現(xiàn)直接選擇排序
選擇排序?qū)崿F(xiàn)代碼如下:
[cpp]?view plaincopy
注:對比冒泡排序和選擇排序之間的區(qū)別
區(qū)別在于:冒泡算法,每次比較如果發(fā)現(xiàn)較小的元素在后面,就交換兩個(gè)相鄰的元素。而選擇排序算法的改進(jìn)在于:先并不急于調(diào)換位置,先從A[1]開始逐個(gè)檢查,看哪個(gè)數(shù)最小就記下該數(shù)所在的位置P,等一躺掃描完畢,再把A[P]和A[1]對調(diào),這時(shí)A[1]到A[10]中最小的數(shù)據(jù)就換到了最前面的位置
所以,選擇排序每掃描一遍數(shù)組,只需要一次真正的交換,而冒泡可能需要很多次。比較的次數(shù)是一樣的。
面試題13:typedef和define有什么區(qū)別
(1)用法不同:typedef用來定義一種數(shù)據(jù)類型的別名,增強(qiáng)程序的可讀性。define主要用來定義常量,以及書寫復(fù)雜使用頻繁的宏。
(2)執(zhí)行時(shí)間不同:typedef是編譯過程的一部分,有類型檢查的功能。define是宏定義,是預(yù)編譯的部分,其發(fā)生在編譯之前,只是簡單的進(jìn)行字符串的替換,不進(jìn)行類型的檢查。
(3)作用域不同:typedef有作用域限定。define不受作用域約束,只要是在define聲明后的引用都是正確的。
(4)對指針的操作不同:typedef和define定義的指針時(shí)有很大的區(qū)別。
注意:typedef定義是語句,因?yàn)榫湮惨由戏痔枴6鴇efine不是語句,千萬不能在句尾加分號;
面試題14:關(guān)鍵字const是什么
const用來定義一個(gè)只讀的變量或?qū)ο蟆V饕獌?yōu)點(diǎn):便于類型檢查、同宏定義一樣可以方便地進(jìn)行參數(shù)的修改和調(diào)整、節(jié)省空間,避免不必要的內(nèi)存分配、可為函數(shù)重載提供參考。
說明:const修飾函數(shù)參數(shù),是一種編程規(guī)范的要求,便于閱讀,一看即知這個(gè)參數(shù)不能被改變,實(shí)現(xiàn)時(shí)不易出錯(cuò)。
面試題15:static有什么作用
static在C中主要用于定義全局靜態(tài)變量、定義局部靜態(tài)變量、定義靜態(tài)函數(shù)。在C++中新增了兩種作用:定義靜態(tài)數(shù)據(jù)成員、靜態(tài)函數(shù)成員。
注意:因?yàn)閟tatic定義的變量分配在靜態(tài)區(qū),所以其定義的變量的默認(rèn)值為0,普通變量的默認(rèn)值為隨機(jī)數(shù),在定義指針變量時(shí)要特別注意。
面試題16:extern有什么作用
extern標(biāo)識的變量或者函數(shù)聲明其定義在別的文件中,提示編譯器遇到此變量和函數(shù)時(shí)在其它模塊中尋找其定義。
面試題17:簡述指針常量與常量指針區(qū)別
指針常量是指定義了一個(gè)指針,這個(gè)指針的值只能在定義時(shí)初始化,其他地方不能改變。其實(shí)指針常量是唯一的,即NULL;常量指針是指定義了一個(gè)指針,這個(gè)指針指向一個(gè)只讀的對象,不能通過常量指針來改變這個(gè)對象的值。
指針常量強(qiáng)調(diào)的是指針的不可改變性,而常量指針強(qiáng)調(diào)的是指針對其所指對象的不可改變性。
注意:無論是指針常量還是常量指針,其最大的用途就是作為函數(shù)的形式參數(shù),保證實(shí)參在被調(diào)用函數(shù)中的不可改變特性。
面試題18:如何避免“野指針”
“野指針”產(chǎn)生原因及解決辦法如下:
(1)指針變量聲明時(shí)沒有被初始化。解決辦法:指針聲明時(shí)初始化,可以是具體的地址值,也可讓它指向NULL。
(2)指針 p 被 free 或者 delete 之后,沒有置為 NULL。解決辦法:指針指向的內(nèi)存空間被釋放后指針應(yīng)該指向NULL。
(3)指針操作超越了變量的作用范圍。解決辦法:在變量的作用域結(jié)束前釋放掉變量的地址空間并且讓指針指向NULL。
注意:“野指針”的解決方法也是編程規(guī)范的基本原則,平時(shí)使用指針時(shí)一定要避免產(chǎn)生“野指針”,在使用指針前一定要檢驗(yàn)指針的合法性。
面試題19:用C編寫一個(gè)死循環(huán)程序
[cpp]?view plaincopy
[cpp]?view plaincopy
面試題20:編碼實(shí)現(xiàn)某一變量某位清0或置1
給定一個(gè)整型變量a,寫兩段代碼,第一個(gè)設(shè)置a的bit 3,第二個(gè)清a的bit 3,在以上兩個(gè)操作中,要保持其他位不變。
筆者認(rèn)為,在對ARM寄存器操作時(shí)會(huì)經(jīng)常用到這一塊,所以要注意這塊:
[cpp]?view plaincopy
還有一個(gè)就是保留某位:
[cpp]?view plaincopy
?
面試題21:a=3,b=5,不用第三變量temp,對a和b的值進(jìn)行交換
如果有第三者temp,a和b交換非常方便:
[cpp]?view plaincopy若無temp,可以這樣做:
a = a + b;
b = a - b;
a = a - b;
當(dāng)然,我們可以利用C語言的位運(yùn)算符:
[cpp]?view plaincopy原理是a ^ b ^ b == a; a ^ b == b ^ a;
面試題22:宏定義的用法,看下面這個(gè)程序,求出結(jié)果
這道題容易出現(xiàn)的錯(cuò)誤結(jié)果是64,得到這個(gè)結(jié)果肯定是這樣理解的(3+5)*(5+3)。其實(shí)并不是,大家要理解宏定義的概念,宏定義只是簡單的符號替換,而不做其他處理,所以這里得到的結(jié)果是 3+5*5+3=31.
大家看看運(yùn)行結(jié)果:
[cpp]?view plaincopy要想得到正確結(jié)果,應(yīng)該怎么樣呢?應(yīng)該這樣改,define s(a,b) (a)*(b),這樣才是正確結(jié)果;
[cpp]?view plaincopy 大家記住這句話,宏定義只是簡單的符號替換!
面試題23:
C語言中,運(yùn)算對象必須是整型數(shù)的運(yùn)算符的有()
A、%????? B、/????? C、%和/????? D、*
答案:A
取余對象必須是整數(shù)型
面試題25:
以下程序執(zhí)行的結(jié)果是__
[cpp]?view plaincopy A、5?? B、6? C、8?? D、9
答案:C
注意宏定義的使用,此處NUM = (3+1)*2+1/2 為8
總結(jié)
以上是生活随笔為你收集整理的C/C++经典面试题的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Python3中urllib详细使用方法
- 下一篇: VC命令行编译参数介绍