C/C++程序員面試易錯題


 

c部分:::::::::::::::::::::::::::::::::::

27、 關鍵字volatile有什么含意? 並給出三個不同的例
子。
【參考答案】一個定義為volatile的變量是說這變量可
能會被意想不到地改變,這樣,編譯器就不會去假設
這個變量的值了。精確地說就是,優化器在用到這個
變量時必須每次都小心地重新讀取這個變量的值,而
不是使用保存在寄存器里的備份。下面是volatile變量
的幾個例子:
1). 並行設備的硬件寄存器(如:狀態寄存器)
2). 一個中斷服務子程序中會訪問到的非自動變量
(Non-automatic variables)
3). 多線程應用中被幾個任務共享的變量

31const 有什么用途?(請至少說明兩種)
【標准答案】: (1)可以定義 const 常量
(2)const 可以修飾函數的參數、返回值,甚至函數
的定義體。被 const 修飾的東西都受到強制保


32、 static有什么用途?(請至少說明兩種)
【標准答案】
1.限制變量的作用域(static全局變量);
2.設置變量的存儲域(static局部變量)。

34、如何引用一個已經定義過的全局變量?
【標准答案】可以用引用頭文件的方式,也可以用
extern關鍵字,如果用引用頭文件方式來引用某個在
頭文件中聲明的全局變理,假定你將那個變量寫錯了
,那么在編譯期間會報錯,如果你用extern方式引用
時,假定你犯了同樣的錯誤,那么在編譯期間不會報
錯,而在連接期間報錯。

35、全局變量可不可以定義在可被多個.C文件包含的
頭文件中?為什么?
【標准答案】可以,在不同的C文件中以static形式來聲
明同名全局變量。可以在不同的C文件中聲明同名的全
局變量,前提是其中只能有一個C文件中對此變量賦初
值,此時連接不會出錯。

37、 Heap與stack的差別。
【標准答案】Heap是堆,stack是棧。
Stack的空間由操作系統自動分配/釋放,Heap上的空
間手動分配/釋放。
Stack空間有限,Heap是很大的自由存儲區
C中的malloc函數分配的內存空間即在堆上,C++中對
應的是new操作符。
程序在編譯期對變量和函數分配內存都在棧上進行,且
程序運行過程中函數調用時參數的傳遞也在棧上進行。

1).全局全局變量本身就是靜態存儲方式, 靜態全局變量當然也是靜態存儲方式。但是他們的作用域,非靜態全局 變量的作用域是整個源程序(多個源文件可以共同使用); 而靜態全局變量則限制了其作用域, 即只在定義該變量的源文件內有效, 在同一源程序的其它源文件中不能使用它。

2).static函數(也叫內部函數)

只能被本文件中的函數調用,而不能被同一程序其它文件中的函數調用。區別於一般的非靜態函數(外部函數) static在c里面可以用來修飾變量,也可以用來修飾函數。 先看用來修飾變量的時候。變量在c里面可分為存在全局數據區、棧和堆里。其實我們平時所說的堆棧是棧而不包含對,不要弄混。

程序的局部變量存在於棧(stack)中,全局
變量存在於靜態數據區 中,動態申請數據存在於堆(
heap)中。

49、什么是預編譯,何時需要預編譯:
【標准答案】1、總是使用不經常改動的大型代碼體
。
2、程序由多個模塊組成,所有模塊都使用一組標准
的包含文件和相同的編譯選項。在這種情況下,可以
將所有包含文件預編譯為一個預編譯頭。

72、 中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提
供一種擴展—讓標准C支持中斷。具代表事實是,產生了一個新的關鍵字
__interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服
務子程序(ISR),請評論一下這段代碼的。
__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf(" Area = %f", area);
return area;
}
【參考答案】這個函數有太多的錯誤了,以至讓人不知從何說起了:
1). ISR 不能返回一個值。如果你不懂這個,那么你不會被雇用的。
2). ISR 不能傳遞參數。如果你沒有看到這一點,你被雇用的機會等同第
一項。
3). 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編
譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做
浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明
智的。
4). 與第三點一脈相承,printf()經常有重入和性能上的問題。如果你丟掉
了第三和第四點,我不會太為難你的。不用說,如果你能得到后兩點,那
么你的被雇用前景越來越光明了。

83、請編寫一個 C 函數,該函數在給定的內存區域搜
索給定的字符,並返回該字符所在位置索引值。
【參考答案】
int search(char *cpSource, int n, char ch) //起始地址,搜索長度,目標字符
{
int i;
for(i=0; i<n && *(cpSource+i) != ch; ++i);
return i;
}

91、寫一個內存拷貝函數,不用任何庫函數.就是前些時
候本版討論的那個問題。
【參考答案】
void* memcpy(void* pvTo, const void* pvFrom, size_t size)
{
assert((pvTo != NULL) && (pvFrom != NULL));
byte* pbTo = pvTo;
byte* pbFrom = pbFrom;
while (size-- > 0)
{
*pbTo++ = *pbFrom++;
}
return pvTo;
}

93、取一個整數a從右端開始的4~7位。
【參考答案】
main()
{
unsigned a,b,c,d;
scanf("%o",&a);
b=a>>4;
c=~(~0<<4);
d=b&c;
printf("%o\n%o\n",a,d);
}


c++ 部分:::::::::::::::::::::::;

11、引用與指針有什么區別?
【參考答案】
1) 引用必須被初始化,指針不必。
2) 引用初始化以后不能被改變,指針可以改變所指的
對象。
3) 不存在指向空值的引用,但是存在指向空值的指針
。

14、函數assert的用法?
【參考答案】斷言assert是僅在debug版本起作用的宏
,用於檢查“不應該“發生的情況。程序員可以把assert
看成一個在任何系統狀態下都可以安全使用的無害測
試手段。

17、有了 malloc/free 為什么還要 new/delete ?
【參考答案】malloc 與 free 是 C++/C 語言的標准庫
函數,new/delete 是 C++的運算符。它們都可用於申
請動態內存和釋放內存。 對於非內部數據類型的對象
而言,光用 maloc/free 無法滿足動態對象的要求。對
象在創建的同時要自動執行構造函數,對象在消亡之
前要自動執行析構函數。由於malloc/free 是庫函數而
不是運算符,不在編譯器控制權限之內,不能夠把執
行構造函數和析構函數的任務強加於 malloc/free。 因
此 C++語言需要一個能完成動態內存分配和初始化工
作的運算符 new,以及一個能完成清理與釋放內存工
作的運算符 delete。注意 new/delete 不是庫函數。

19、C++是不是類型安全的?
【參考答案】不是。兩個不同類型的指針之間可以強制
轉換(用reinterpret cast)。

21、用C++寫個程序,如何判斷一個操作系統是16位
還是32位的?
【標准答案】定義一個指針p,打印出sizeof(p),如果節
后是4,則表示該操作系統是32位,打印結果是2,表
示是16位。

22、 .用C++寫個程序,如何判斷一個操作系統是16位
還是32位的?不能用sizeof()函數。
【參考答案】
int a = ~0;
if( a>65536 )
{
cout<<"32 bit"<<endl;
}
else
{
cout<<"16 bit"<<endl;
}

24、多態類中的虛函數表是Compile-Time,還是Run-
Time時建立的?
【標准答案】虛擬函數表是在編譯期就建立了,各個虛
擬函數這時被組織成了一個虛擬函數的入口地址的數
組.而對象的隱藏成員--虛擬函數表指針是在運行期--也
就是構造函數被調用時進行初始化的,這是實現多態的
關鍵。

25、錯誤的轉義字符是 ()
A.'\091'
B.'\\'
C.'\0'
D.'\'‘
【標准答案】A

28、內存的分配方式有幾種?
【參考答案】一、從靜態存儲區域分配。內存在程序
編譯的時候就已經分配好,這塊內存在程序的整個運
行期間都存在。例如全局變量。二、在棧上創建。在
執行函數時,函數內局部變量的存儲單元都可以在棧
上創建,函數執行結束時這些存儲單元自動被釋放。
棧內存分配運算內置於處理器的指令集中,效率很高
,但是分配的內存容量有限。
三、從堆上分配,亦稱動態內存分配。程序在運行的
時候用malloc或new申請任意多少的內存,程序員自己
負責在何時用free或delete釋放內存。動態內存的生存
期由我們決定,使用非常靈活,但問題也最多。

29float a,b,c ,問等式 (a+b)+c==(b+a)+c 和
(a+b)+c==(a+c)+b能否成立?
【參考答案】兩者都不行。在比較float或double時,不
能簡單地比較。由於計算誤差,相等的概率很低。應
判斷兩數之差是否落在區間(-e,e)內。這個e應比浮點
數的精度大一個數量級。

32、In C++, what does "explicit" mean? what does
"protected" mean?
【標准答案】c++中的explicit關鍵字用來修飾類的構造
函數,表明該構造函數是顯式的,在某些情況下,我
們要求類的使用者必須顯示調用類的構造函數時就需
要使用explicit,反之默認類型轉換可能會造成無法預期
的問題。protected控制的是一個函數對一個類的成員
(包括成員變量及成員方法)的訪問權限。protected
成員只有該類的成員函數及其派生類的成員函數可以
訪問。

32、In C++, what does "explicit" mean? what does
"protected" mean?
【標准答案】c++中的explicit關鍵字用來修飾類的構造
函數,表明該構造函數是顯式的,在某些情況下,我
們要求類的使用者必須顯示調用類的構造函數時就需
要使用explicit,反之默認類型轉換可能會造成無法預期
的問題。protected控制的是一個函數對一個類的成員
(包括成員變量及成員方法)的訪問權限。protected
成員只有該類的成員函數及其派生類的成員函數可以
訪問。

33、重復多次fclose一個打開過一次的FILE *fp指針會
有什么結果,並請解釋。
【參考答案】考察點:導致文件描述符結構中指針指向
的內存被重復釋放,進而導致一些不可預期的異常。

34、為什么數組名作為參數,會改變數組的內容,而
其它類型如int卻不會改變變量的值?
【參考答案】當數組名作為參數時,傳遞的實際上是地
址。而其他類型如int作為參數時,由於函數參數值實
質上是實參的一份拷貝,被調函數內部對形參的改變
並不影響實參的值。

40、重載(overload)、重寫(override,有的書也叫做“
覆蓋”)、重定義(redefinition)的區別?
【標准答案】
名稱
名字空間
區別
重載 同一名字空間 是指允許存在多個同名函數,而這些函數的參
數表不同。
重定義/隱
藏 不同名字空間 用於繼承,派生類與基類的函數同名,屏蔽基
類的函數
重寫/覆蓋 不同名字空間 用於繼承,子類重新定義復類虛函數的方法

41、多態的作用?
【參考答案】主要是兩個:1. 隱藏實現細節,使得代
碼能夠模塊化;擴展代碼模塊,實現代碼重用;2. 接
口重用:為了類在繼承和派生的時候,保證使用家族
中任一類的實例的某一屬性時的正確調用。

44、 C++里面是不是所有的動作都是main()引起的?
如果不是,請舉例。
【參考答案】比如全局變量的初始化,就不是由main函
數引起的。

47、“newin c++ is a:
A. library function like malloc in c
B. key word
C. operator
D. none of the above
【參考答案】C。malloc是庫函數,不在編譯器控制范
圍之內;new是運算符,在編譯器控制范圍之內。
調用malloc時,從堆中申請內存;調用new時,從堆中
申請內存並為內存調用構造函數。

48、對於C++中類(class) 與結構(struct)的描述正確的為:
A,類中的成員默認是private的,當是可以聲明public,private
和protected,結構中定義的成員默認的都是public;
B,結構中不允許定義成員函數,當是類中可以定義成員函數;
C,結構實例使用malloc() 動態創建,類對象使用new 操作符動
態分配內存;
D,結構和類對象都必須使用new 創建;
E,結構中不可以定義虛函數,當是類中可以定義虛函數.
F,結構不可以存在繼承關系,當是類可以存在繼承關系.
【標准答案】A,D

50、C++程序下列說法正確的有:
A,對調用的虛函數和模板類都進行遲后編譯.
B,基類與子類中函數如果要構成虛函數,除了要求在基
類中用virtual 聲名,而且必須名字相同且參數類型相同
返回類型相同。
C,重載的類成員函數都必須要:或者返回類型不同,或者
參數數目不同,或者參數序列的類型不同.
D,靜態成員函數和內聯函數不能是虛函數,友員函數和
構造函數也不能是虛函數,但是析構函數可以是虛函數.
【標准答案】A

51、在C++中有沒有純虛構造函數?
【標准答案】構造函數不能是虛的。只能有虛的析構
函數。

60、所有的運算符都能重載嗎?
【參考答案】不能被重載的運算符
在 C++運算符集合中,有一些運算符是不允許被重載
的。這種限制是出於安全方面的考慮,可防止錯誤和
混亂。 (1)不能改變 C++內部數據類型(如 int,float
等)的運算符。 (2)不能重載‘.’,因為‘.’在類中對任
何成員都有意義,已經成為標准用法。 (3)不能重
載目前 C++運算符集合中沒有的符號,如#,@,$等。
原因有兩點,一是難以理解,二是難以確定優先級。
(4)對已經存在的運算符進行重載時,不能改變優先級
規則,否則將引起混亂。

61、基類的析構函數不是虛函數,會帶來什么問題?
【參考答案】派生類的析構函數用不上,會造成資源
的泄漏。

76、以下三條輸出語句分別輸出什么?
char str1[]
= "abc";
char str2[]
= "abc";
const char str3[] = "abc";
const char str4[] = "abc";
const char* str5 = "abc";
const char* str6 = "abc";
cout << boolalpha << ( str1==str2 ) << endl; // 輸出什么?
cout << boolalpha << ( str3==str4 ) << endl; // 輸出什么?
cout << boolalpha << ( str5==str6 ) << endl; // 輸出什么?
【參考答案】分別輸出false,false,true。str1和str2都是字符數組,每個都有其自己
的存儲區,它們的值則是各存儲區首地址,不等;str3和str4同上,只是按const語
義,它們所指向的數據區不能修改。str5和str6並非數組而是字符指針,並不分配
存儲區,其后的“abc”以常量形式存於靜態數據區,而它們自己僅是指向該區首地址
的指針,相等。

77、以下代碼有什么問題?
cout << (true?1:"1") << endl;
【參考答案】三元表達式“?:”問號后面的兩個操作數必
須為同一類型。

79、以下代碼中的輸出語句輸出0嗎,為什么?
struct CLS
{
int m_i;
CLS( int i ) : m_i(i) {}
CLS()
{
CLS(0);
}
};
CLS obj;
cout << obj.m_i << endl;
【標准答案】不能。在默認構造函數內部再調用帶參的構造函數屬用戶
行為而非編譯器行為,亦即僅執行函數調用,而不會執行其后的初始化
表達式。只有在生成對象時,初始化表達式才會隨相應的構造函數一起
調用。

82、在排序方法中,關鍵碼比較次數與記錄地初始排
列無關的是()
A. Shell排序
B. 歸並排序
C. 直接插入排序
D. 選擇排序
【標准答案】D

83、代碼
void func()
{
static int val;
...
} 中,變量val的內存地址位於:
A. 已初始化數據段 B.未初始化數據段
C.堆
D.棧
【標准答案】A

85、寫出判斷ABCD四個表達式的是否正確, 若正確,
寫出經過表達式中 a的值。
int a = 4;
(A)a += (a++); (B) a += (++a) ;
(C)(a++) += a;(D) (++a) += (a++);
a = ?
【參考答案】C錯誤,左側不是一個有效變量,不能賦
值,可改為(++a) += a;改后答案依次為9,10,10,11
1.15.1,大小端模式對 union 類型數據的影響
下面再看一個例子:
union
{
int i;
char a[2];
}*p, u;
p = &u;
p->a[0] = 0x39;
p->a[1] = 0x38;
p.i 的值應該為多少呢?
這里需要考慮存儲模式:大端模式和小端模式。
大端模式(Big_endian):字數據的高字節存儲在低地址中,而字數據的低字節則存放
在高地址中。
小端模式(Little_endian):字數據的高字節存儲在高地址中,而字數據的低字節則存放
在低地址中。
union 型數據所占的空間等於其最大的成員所占的空間。對 union 型的成員的存取都是
相對於該聯合體基地址的偏移量為 0 處開始,也就是聯合體的訪問不論對哪個變量的存取都
是從 union 的首地址位置開始。如此一解釋,上面的問題是否已經有了答案呢?
 
 

 



 


















注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2020 ITdaan.com