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