| 
	最近因?yàn)檎夜ぷ?,收集了很多C語(yǔ)言方面方面的面試題以及答案?,F(xiàn)在新工作搞定了,決定把這些資料發(fā)出來(lái),送給有需要的朋友,免得再象我一樣到處搜尋,實(shí)在辛苦。
 
	發(fā)布之前先申明兩點(diǎn):1 所有資料來(lái)自網(wǎng)絡(luò)(主要是CSDN),本人只是收集和轉(zhuǎn)發(fā)。
 2 所有問(wèn)題解答(尤其是代碼)只是參考,不保證正確。
 
	先發(fā)基本問(wèn)題,再發(fā)編程問(wèn)題..........
 
	想成為嵌入式程序員應(yīng)知道的0x10個(gè)基本問(wèn)題:預(yù)處理器(Preprocessor)
 
	1 . 用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問(wèn)題)#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
 我在這想看到幾件事情:
 1) #define 語(yǔ)法的基本知識(shí)(例如:不能以分號(hào)結(jié)束,括號(hào)的使用,等等)
 2)懂得預(yù)處理器將為你計(jì)算常數(shù)表達(dá)式的值,因此,直接寫(xiě)出你是如何計(jì)算一年中有多少秒而不是計(jì)算出實(shí)際的值,是更清晰而沒(méi)有代價(jià)的。
 3) 意識(shí)到這個(gè)表達(dá)式將使一個(gè)16位機(jī)的整型數(shù)溢出-因此要用到長(zhǎng)整型符號(hào)L,告訴編譯器這個(gè)常數(shù)是的長(zhǎng)整型數(shù)。
 4) 如果你在你的表達(dá)式中用到UL(表示無(wú)符號(hào)長(zhǎng)整型),那么你有了一個(gè)好的起點(diǎn)。記住,第一印象很重要。
 
	2 . 寫(xiě)一個(gè)"標(biāo)準(zhǔn)"宏MIN ,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。#define MIN(A,B) ((A) <= (B) ? (A) : (B))
 這個(gè)測(cè)試是為下面的目的而設(shè)的:
 1) 標(biāo)識(shí)#define在宏中應(yīng)用的基本知識(shí)。這是很重要的。因?yàn)樵?nbsp; 嵌入(inline)操作符 變?yōu)闃?biāo)準(zhǔn)C的一部分之前,宏是方便產(chǎn)生嵌入代碼的唯一方法,對(duì)于嵌入式系統(tǒng)來(lái)說(shuō),為了能達(dá)到要求的性能,嵌入代碼經(jīng)常是必須的方法。
 2)三重條件操作符的知識(shí)。這個(gè)操作符存在C語(yǔ)言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)化的代碼,了解這個(gè)用法是很重要的。
 3) 懂得在宏中小心地把參數(shù)用括號(hào)括起來(lái)
 4) 我也用這個(gè)問(wèn)題開(kāi)始討論宏的副作用,例如:當(dāng)你寫(xiě)下面的代碼時(shí)會(huì)發(fā)生什么事?
 least = MIN(*p++, b);
 
	3. 預(yù)處理器標(biāo)識(shí)#error的目的是什么?如果你不知道答案,請(qǐng)看參考文獻(xiàn)1。這問(wèn)題對(duì)區(qū)分一個(gè)正常的伙計(jì)和一個(gè)書(shū)呆子是很有用的。只有書(shū)呆子才會(huì)讀C語(yǔ)言課本的附錄去找出象這種問(wèn)題的答案。當(dāng)然如果你不是在找一個(gè)書(shū)呆子,那么應(yīng)試者最好希望自己不要知道答案。
 
	死循環(huán)(Infinite loops)
 
	4. 嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么樣用C編寫(xiě)死循環(huán)呢?這個(gè)問(wèn)題用幾個(gè)解決方案。我首選的方案是:
 
	while(1){
 
	}
 
	一些程序員更喜歡如下方案:
 
	for(;;){
 
	}
 
	這個(gè)實(shí)現(xiàn)方式讓我為難,因?yàn)檫@個(gè)語(yǔ)法沒(méi)有確切表達(dá)到底怎么回事。如果一個(gè)應(yīng)試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機(jī)會(huì)去探究他們這樣做的基本原理。如果他們的基本答案是:"我被教著這樣做,但從沒(méi)有想到過(guò)為什么。"這會(huì)給我留下一個(gè)壞印象。
 
	第三個(gè)方案是用 gotoLoop:
 ...
 goto Loop;
 應(yīng)試者如給出上面的方案,這說(shuō)明或者他是一個(gè)匯編語(yǔ)言程序員(這也許是好事)或者他是一個(gè)想進(jìn)入新領(lǐng)域的BASIC/FORTRAN程序員。
 
	數(shù)據(jù)聲明(Data declarations)
 
	5. 用變量a給出下面的定義a) 一個(gè)整型數(shù)(An integer)
 b)一個(gè)指向整型數(shù)的指針( A pointer to an integer)
 c)一個(gè)指向指針的的指針,它指向的指針是指向一個(gè)整型數(shù)( A pointer to a pointer to an intege)r
 d)一個(gè)有10個(gè)整型數(shù)的數(shù)組( An array of 10 integers)
 e) 一個(gè)有10個(gè)指針的數(shù)組,該指針是指向一個(gè)整型數(shù)的。(An array of 10 pointers to integers)
 f) 一個(gè)指向有10個(gè)整型數(shù)數(shù)組的指針( A pointer to an array of 10 integers)
 g) 一個(gè)指向函數(shù)的指針,該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù)(A pointer to a function that takes an integer as an argument and returns an integer)
 h)
一個(gè)有10個(gè)指針的數(shù)組,該指針指向一個(gè)函數(shù),該函數(shù)有一個(gè)整型參數(shù)并返回一個(gè)整型數(shù)( An array of ten pointers to
functions that take an integer argument and return an integer )
 
	答案是: a) int a; // An integer
 b) int *a; // A pointer to an integer
 c) int **a; // A pointer to a pointer to an integer
 d) int a[10]; // An array of 10 integers
 e) int *a[10]; // An array of 10 pointers to integers
 f) int (*a)[10]; // A pointer to an array of 10 integers
 g) int (*a)(int); // A pointer to a function a that takes an integer argument and returns an integer
 h) int (*a[10])(int); // An array of 10 pointers to functions that take an integer argument and return an integer
 
	人們經(jīng)常聲稱(chēng)這里有幾個(gè)問(wèn)題是那種要翻一下書(shū)才能回答的問(wèn)題,我同意這種說(shuō)法。當(dāng)我寫(xiě)這篇文章時(shí),為
了確定語(yǔ)法的正確性,我的確查了一下書(shū)。但是當(dāng)我被面試的時(shí)候,我期望被問(wèn)到這個(gè)問(wèn)題(或者相近的問(wèn)題)。因?yàn)樵诒幻嬖嚨倪@段時(shí)間里,我確定我知道這個(gè)問(wèn)
題的答案。應(yīng)試者如果不知道所有的答案(或至少大部分答案),那么也就沒(méi)有為這次面試做準(zhǔn)備,如果該面試者沒(méi)有為這次面試做準(zhǔn)備,那么他又能為什么出準(zhǔn)備
呢?
 
	Static 
 
	6. 關(guān)鍵字static的作用是什么?這個(gè)簡(jiǎn)單的問(wèn)題很少有人能回答完全。在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用:
 1)在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。
 2) 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量。
 3) 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。
 
	大多數(shù)應(yīng)試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個(gè)應(yīng)試者的嚴(yán)重的缺點(diǎn),因?yàn)樗@然不懂得本地化數(shù)據(jù)和代碼范圍的好處和重要性。
 
	Const 
 
	7.關(guān)鍵字const有什么含意?我只要一聽(tīng)到被面試者說(shuō):"const意味著常數(shù)",我就
知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded
Systems
Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒(méi)有讀到那篇文章,只要能說(shuō)出const意味著"只讀"就可
以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。(如果你想知道更詳細(xì)的答案,仔細(xì)讀一下Saks的文章吧。)
 如果應(yīng)試者能正確回答這個(gè)問(wèn)題,我將問(wèn)他一個(gè)附加的問(wèn)題:
 下面的聲明都是什么意思?
 
	const int a;int const a;
 const int *a;
 int * const a;
 int const * a const;
 
	/******/前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。第三個(gè)意味著a是一個(gè)指向常整型數(shù)
的指針(也就是,整型數(shù)是不可修改的,但指針可以)。第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改
的)。最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。如果應(yīng)試者能正確回答這些問(wèn)
題,那么他就給我留下了一個(gè)好印象。順帶提一句,也許你可能會(huì)問(wèn),即使不用關(guān)鍵字
const,也還是能很容易寫(xiě)出功能正確的程序,那么我為什么還要如此看重關(guān)鍵字const呢?我也如下的幾下理由:
 1)
關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上,聲明一個(gè)參數(shù)為常量是為了告訴了用戶(hù)這個(gè)參數(shù)的應(yīng)用目的。如果你曾花很多時(shí)間清理
其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人來(lái)清理的。)
 2) 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
 3) 合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無(wú)意的代碼修改。簡(jiǎn)而言之,這樣可以減少bug的出現(xiàn)。
 
	Volatile
 
	8. 關(guān)鍵字volatile有什么含意?并給出三個(gè)不同的例子。一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說(shuō)就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:
 1) 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
 2) 一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Non-automatic variables)
 3) 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
 
	回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問(wèn)題。搞嵌入式的家伙們經(jīng)常同硬件、中斷、RTOS等等打交道,所有這些都要求用到volatile變量。不懂得volatile的內(nèi)容將會(huì)帶來(lái)災(zāi)難。假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑是否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。
 1)一個(gè)參數(shù)既可以是const還可以是volatile嗎?解釋為什么。
 2); 一個(gè)指針可以是volatile 嗎?解釋為什么。
 3); 下面的函數(shù)有什么錯(cuò)誤:
 
	int square(volatile int *ptr){
 return *ptr * *ptr;
 }
 
	下面是答案:1)是的。一個(gè)例子是只讀的狀態(tài)寄存器。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭K莄onst因?yàn)槌绦虿粦?yīng)該試圖去修改它。
 2); 是的。盡管這并不很常見(jiàn)。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
 3) 這段代碼有點(diǎn)變態(tài)。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類(lèi)似下面的代碼:
 
	int square(volatile int *ptr) {
 int a,b;
 a = *ptr;
 b = *ptr;
 return a * b;
 }
 
	由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結(jié)果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:
 
	long square(volatile int *ptr) {
 int a;
 a = *ptr;
 return a * a;
 }
 
	位操作(Bit manipulation) 
 
	9. 嵌入式系統(tǒng)總是要用戶(hù)對(duì)變量或寄存器進(jìn)行位操作。給定一個(gè)整型變量a,寫(xiě)兩段代碼,第一個(gè)設(shè)置a的bit 3,第二個(gè)清除a 的bit 3。在以上兩個(gè)操作中,要保持其它位不變。對(duì)這個(gè)問(wèn)題有三種基本的反應(yīng)
 1)不知道如何下手。該被面者從沒(méi)做過(guò)任何嵌入式系統(tǒng)的工作。
 2)
用bit fields。Bit
fields是被扔到C語(yǔ)言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時(shí)也保證了的你的代碼是不可重用的。我最近不幸看到
Infineon為其較復(fù)雜的通信芯片寫(xiě)的驅(qū)動(dòng)程序,它用到了bit fields因此完全對(duì)我無(wú)用,因?yàn)槲业木幾g器用其它的方式來(lái)實(shí)現(xiàn)bit
fields的。從道德講:永遠(yuǎn)不要讓一個(gè)非嵌入式的家伙粘實(shí)際硬件的邊。
 3) 用 #defines 和 bit masks 操作。這是一個(gè)有極高可移植性的方法,是應(yīng)該被用到的方法。最佳的解決方案如下:
 
	#define BIT3 (0x1 << 3)static int a;
 
	void set_bit3(void) {
 a |= BIT3;
 }
 void clear_bit3(void)
 {
 a &= ~BIT3;
 }
 
	一些人喜歡為設(shè)置和清除值而定義一個(gè)掩碼同時(shí)定義一些說(shuō)明常數(shù),這也是可以接受的。我希望看到幾個(gè)要點(diǎn):說(shuō)明常數(shù)、|=和&=~操作。
 
	訪問(wèn)固定的內(nèi)存位置(Accessing fixed memory locations)
 
	10. 嵌入式系統(tǒng)經(jīng)常具有要求程序員去訪問(wèn)某特定的內(nèi)存位置的特點(diǎn)。在某工程中,要求設(shè)置一絕對(duì)地址為0x67a9的整型變量的值為0xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫(xiě)代碼去完成這一任務(wù)。這一問(wèn)題測(cè)試你是否知道為了訪問(wèn)一絕對(duì)地址把一個(gè)整型數(shù)強(qiáng)制轉(zhuǎn)換(typecast)為一指針是合法的。這一問(wèn)題的實(shí)現(xiàn)方式隨著個(gè)人風(fēng)格不同而不同。典型的類(lèi)似代碼如下:
 int *ptr;
 ptr = (int *)0x67a9;
 *ptr = 0xaa55;
 
	 A more obscure approach is: 一個(gè)較晦澀的方法是:
 
	    *(int * const)(0x67a9) = 0xaa55;
 
	即使你的品味更接近第二種方案,但我建議你在面試時(shí)使用第一種方案。
 
	中斷(Interrupts) 
 
	11.
中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開(kāi)發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字
__interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個(gè)中斷服務(wù)子程序(ISR),請(qǐng)?jiān)u論一下這段代碼的。
 
	__interrupt double compute_area (double radius) {
 double area = PI * radius * radius;
 printf("\nArea = %f", area);
 return area;
 }
 
	這個(gè)函數(shù)有太多的錯(cuò)誤了,以至讓人不知從何說(shuō)起了:1)ISR 不能返回一個(gè)值。如果你不懂這個(gè),那么你不會(huì)被雇用的。
 2) ISR 不能傳遞參數(shù)。如果你沒(méi)有看到這一點(diǎn),你被雇用的機(jī)會(huì)等同第一項(xiàng)。
 3) 在許多的處理器/編譯器中,浮點(diǎn)一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點(diǎn)運(yùn)算。此外,ISR應(yīng)該是短而有效率的,在ISR中做浮點(diǎn)運(yùn)算是不明智的。
 4) 與第三點(diǎn)一脈相承,printf()經(jīng)常有重入和性能上的問(wèn)題。如果你丟掉了第三和第四點(diǎn),我不會(huì)太為難你的。不用說(shuō),如果你能得到后兩點(diǎn),那么你的被雇用前景越來(lái)越光明了。
 
	代碼例子(Code examples)
 
	12 . 下面的代碼輸出是什么,為什么?
 
	void foo(void){
 unsigned int a = 6;
 int b = -20;
 (a+b > 6) ? puts("> 6") : puts("<= 6");
 }
 這
個(gè)問(wèn)題測(cè)試你是否懂得C語(yǔ)言中的整數(shù)自動(dòng)轉(zhuǎn)換原則,我發(fā)現(xiàn)有些開(kāi)發(fā)者懂得極少這些東西。不管如何,這無(wú)符號(hào)整型問(wèn)題的答案是輸出是
">6"。原因是當(dāng)表達(dá)式中存在有符號(hào)類(lèi)型和無(wú)符號(hào)類(lèi)型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無(wú)符號(hào)類(lèi)型。因此-20變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式
計(jì)算出的結(jié)果大于6。這一點(diǎn)對(duì)于應(yīng)當(dāng)頻繁用到無(wú)符號(hào)數(shù)據(jù)類(lèi)型的嵌入式系統(tǒng)來(lái)說(shuō)是豐常重要的。如果你答錯(cuò)了這個(gè)問(wèn)題,你也就到了得不到這份工作的邊緣。
 
	13. 評(píng)價(jià)下面的代碼片斷:
 
	unsigned int zero = 0;unsigned int compzero = 0xFFFF;
 /*1's complement of zero */
 
	對(duì)于一個(gè)int型不是16位的處理器為說(shuō),上面的代碼是不正確的。應(yīng)編寫(xiě)如下:
 
	unsigned int compzero = ~0;
 
	這一問(wèn)題真正能揭露出應(yīng)試者是否懂得處理器字長(zhǎng)的重要性。在我的經(jīng)驗(yàn)里,好的嵌入式程序員非常準(zhǔn)確地明白硬件的細(xì)節(jié)和它的局限,然而PC機(jī)程序往往把硬件作為一個(gè)無(wú)法避免的煩惱。到
了這個(gè)階段,應(yīng)試者或者完全垂頭喪氣了或者信心滿(mǎn)滿(mǎn)志在必得。如果顯然應(yīng)試者不是很好,那么這個(gè)測(cè)試就在這里結(jié)束了。但如果顯然應(yīng)試者做得不錯(cuò),那么我就
扔出下面的追加問(wèn)題,這些問(wèn)題是比較難的,我想僅僅非常優(yōu)秀的應(yīng)試者能做得不錯(cuò)。提出這些問(wèn)題,我希望更多看到應(yīng)試者應(yīng)付問(wèn)題的方法,而不是答案。不管如
何,你就當(dāng)是這個(gè)娛樂(lè)吧...
 
	動(dòng)態(tài)內(nèi)存分配(Dynamic memory allocation) 
 
	14. 盡管不像非嵌入式計(jì)算機(jī)那么常見(jiàn),嵌入式系統(tǒng)還是有從堆(heap)中動(dòng)態(tài)分配內(nèi)存的過(guò)程的。那么嵌入式系統(tǒng)中,動(dòng)態(tài)分配內(nèi)存可能發(fā)生的問(wèn)題是什么?這
里,我期望應(yīng)試者能提到內(nèi)存碎片,碎片收集的問(wèn)題,變量的持行時(shí)間等等。這個(gè)主題已經(jīng)在ESP雜志中被廣泛地討論過(guò)了(主要是 P.J.
Plauger, 他的解釋遠(yuǎn)遠(yuǎn)超過(guò)我這里能提到的任何解釋?zhuān)?,所有回過(guò)頭看一下這些雜志吧!讓?xiě)?yīng)試者進(jìn)入一種虛假的安全感覺(jué)后,我拿出這么一個(gè)小節(jié)目:
 下面的代碼片段的輸出是什么,為什么?
 
	char *ptr;if ((ptr = (char *)malloc(0)) == NULL)
 puts("Got a null pointer");
 else
 puts("Got a valid pointer");
 
	這是一個(gè)有趣的問(wèn)題。最近在我的一個(gè)同事不經(jīng)意把0值傳給了函數(shù)malloc,得到了一個(gè)合法的指針
之后,我才想到這個(gè)問(wèn)題。這就是上面的代碼,該代碼的輸出是"Got a valid
pointer"。我用這個(gè)來(lái)開(kāi)始討論這樣的一問(wèn)題,看看被面試者是否想到庫(kù)例程這樣做是正確。得到正確的答案固然重要,但解決問(wèn)題的方法和你做決定的基
本原理更重要些。
 
	Typedef 
 15 Typedef 在C語(yǔ)言中頻繁用以聲明一個(gè)已經(jīng)存在的數(shù)據(jù)類(lèi)型的同義字。也可以用預(yù)處理器做類(lèi)似的事。例如,思考一下下面的例子:
 
	#define dPS struct s *typedef struct s * tPS;
 
	以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個(gè)指向結(jié)構(gòu)s指針。哪種方法更好呢?(如果有的話(huà))為什么?這是一個(gè)非常微妙的問(wèn)題,任何人答對(duì)這個(gè)問(wèn)題(正當(dāng)?shù)脑颍┦菓?yīng)當(dāng)被恭喜的。答案是:typedef更好。思考下面的例子:
 
	dPS p1,p2;tPS p3,p4;
 
	第一個(gè)擴(kuò)展為
 
	struct s * p1, p2;.
 上面的代碼定義p1為一個(gè)指向結(jié)構(gòu)的指,p2為一個(gè)實(shí)際的結(jié)構(gòu),這也許不是你想要的。第二個(gè)例子正確地定義了p3 和p4 兩個(gè)指針?;逎恼Z(yǔ)法
 
	16 . C語(yǔ)言同意一些令人震驚的結(jié)構(gòu),下面的結(jié)構(gòu)是合法的嗎,如果是它做些什么?
 
	int a = 5, b = 7, c;c = a+++b;
 
	這個(gè)問(wèn)題將做為這個(gè)測(cè)驗(yàn)的一個(gè)愉快的結(jié)尾。不管你相不相信,上面的例子是完全合乎語(yǔ)法的。問(wèn)題是編譯器如何處理它?水平不高的編譯作者實(shí)際上會(huì)爭(zhēng)論這個(gè)問(wèn)題,根據(jù)最處理原則,編譯器應(yīng)當(dāng)能處理盡可能所有合法的用法。因此,上面的代碼被處理成:
 
	c = a++ + b;
 
	因此, 這段代碼持行后a = 6, b = 7, c = 12。如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個(gè)當(dāng)作問(wèn)題。我發(fā)現(xiàn)這個(gè)問(wèn)題的最大好處是這是一個(gè)關(guān)于代碼編寫(xiě)風(fēng)格,代碼的可讀性,代碼的可修改性的好的話(huà)題。
 
	華為筆試題 1.寫(xiě)出判斷ABCD四個(gè)表達(dá)式的是否正確, 若正確, 寫(xiě)出經(jīng)過(guò)表達(dá)式中 a的值(3分)
 int a = 4;
 (A)a += (a++); (B) a += (++a) ;(C) (a++) += a;(D) (++a) += (a++);
 a = ?
 答:C錯(cuò)誤,左側(cè)不是一個(gè)有效變量,不能賦值,可改為(++a) += a;
 改后答案依次為9,10,10,11
 
	2.某32位系統(tǒng)下, C++程序,請(qǐng)計(jì)算sizeof 的值(5分).char str[] = “http://www./”
 char *p = str ;
 int n = 10;
 請(qǐng)計(jì)算
 sizeof (str ) = ?(1)
 sizeof ( p ) = ?(2)
 sizeof ( n ) = ?(3)
 void Foo ( char str[100]){
 請(qǐng)計(jì)算
 sizeof( str ) = ?(4)
 }
 void *p = malloc( 100 );
 請(qǐng)計(jì)算
 sizeof ( p ) = ?(5)
 答:(1)17 (2)4 (3) 4 (4)4 (5)4
 
	3. 回答下面的問(wèn)題. (4分)(1).頭文件中的 ifndef/define/endif 干什么用?預(yù)處理
 答:防止頭文件被重復(fù)引用
 (2). #i nclude 和 #i nclude “filename.h” 有什么區(qū)別?
 答:前者用來(lái)包含開(kāi)發(fā)環(huán)境提供的庫(kù)頭文件,后者用來(lái)包含自己編寫(xiě)的頭文件。
 (3).在C++ 程序中調(diào)用被 C 編譯器編譯后的函數(shù),為什么要加 extern “C”聲明?
 答:函數(shù)和變量被C++編譯后在符號(hào)庫(kù)中的名字與C語(yǔ)言的不同,被extern "C"修飾的變
 量和函數(shù)是按照C語(yǔ)言方式編譯和連接的。由于編譯后的名字不同,C++程序不能直接調(diào)
 用C 函數(shù)。C++提供了一個(gè)C 連接交換指定符號(hào)extern“C”來(lái)解決這個(gè)問(wèn)題。
 (4). switch()中不允許的數(shù)據(jù)類(lèi)型是?
 答:實(shí)型
 
	4. 回答下面的問(wèn)題(6分)(1).Void GetMemory(char **p, int num){
 *p = (char *)malloc(num);
 }
 void Test(void){
 char *str = NULL;
 GetMemory(&str, 100);
 strcpy(str, "hello");
 printf(str);
 }
 請(qǐng)問(wèn)運(yùn)行Test 函數(shù)會(huì)有什么樣的結(jié)果?
 答:輸出“hello”
 (2). void Test(void){
 char *str = (char *) malloc(100);
 strcpy(str, “hello”);
 free(str);
 if(str != NULL){
 strcpy(str, “world”);
 printf(str);
 }
 }
 請(qǐng)問(wèn)運(yùn)行Test 函數(shù)會(huì)有什么樣的結(jié)果?
 答:輸出“world”
 (3). char *GetMemory(void){
 char p[] = "hello world";
 return p;
 }
 void Test(void){
 char *str = NULL;
 str = GetMemory();
 printf(str);
 }
 請(qǐng)問(wèn)運(yùn)行Test 函數(shù)會(huì)有什么樣的結(jié)果?
 答:無(wú)效的指針,輸出不確定
 
	5. 編寫(xiě)strcat函數(shù)(6分)已知strcat函數(shù)的原型是char *strcat (char *strDest, const char *strSrc);
 其中strDest 是目的字符串,strSrc 是源字符串。
 (1)不調(diào)用C++/C 的字符串庫(kù)函數(shù),請(qǐng)編寫(xiě)函數(shù) strcat
 答:
 VC源碼:
 char * __cdecl strcat (char * dst, const char * src)
 {
 char * cp = dst;
 while( *cp )
 cp++; /* find end of dst */
 while( *cp++ = *src++ ) ; /* Copy src to end of dst */
 return( dst ); /* return dst */
 }
 (2)strcat能把strSrc 的內(nèi)容連接到strDest,為什么還要char * 類(lèi)型的返回值?
 答:方便賦值給其他變量
 
	6.MFC中CString是類(lèi)型安全類(lèi)么?答:不是,其它數(shù)據(jù)類(lèi)型轉(zhuǎn)換到CString可以使用CString的成員函數(shù)Format來(lái)轉(zhuǎn)換
 
	7.C++中為什么用模板類(lèi)。答:(1)可用來(lái)創(chuàng)建動(dòng)態(tài)增長(zhǎng)和減小的數(shù)據(jù)結(jié)構(gòu)
 (2)它是類(lèi)型無(wú)關(guān)的,因此具有很高的可復(fù)用性。
 (3)它在編譯時(shí)而不是運(yùn)行時(shí)檢查數(shù)據(jù)類(lèi)型,保證了類(lèi)型安全
 (4)它是平臺(tái)無(wú)關(guān)的,可移植性
 (5)可用于基本數(shù)據(jù)類(lèi)型
 
	8.CSingleLock是干什么的。答:同步多個(gè)線程對(duì)一個(gè)數(shù)據(jù)類(lèi)的同時(shí)訪問(wèn)
 
	9.NEWTEXTMETRIC 是什么。答:物理字體結(jié)構(gòu),用來(lái)設(shè)置字體的高寬大小
 
	10.程序什么時(shí)候應(yīng)該使用線程,什么時(shí)候單線程效率高。答:1.耗時(shí)的操作使用線程,提高應(yīng)用程序響應(yīng)
 2.并行操作時(shí)使用線程,如C/S架構(gòu)的服務(wù)器端并發(fā)線程響應(yīng)用戶(hù)的請(qǐng)求。
 3.多CPU系統(tǒng)中,使用線程提高CPU利用率
 4.改善程序結(jié)構(gòu)。一個(gè)既長(zhǎng)又復(fù)雜的進(jìn)程可以考慮分為多個(gè)線程,成為幾個(gè)獨(dú)立或半獨(dú)
 立的運(yùn)行部分,這樣的程序會(huì)利于理解和修改。
 其他情況都使用單線程。
 
	11.Windows是內(nèi)核級(jí)線程么。答:見(jiàn)下一題
 
	12.Linux有內(nèi)核級(jí)線程么。答:線程通常被定義為一個(gè)進(jìn)程中代碼的不同執(zhí)行路線。從實(shí)現(xiàn)方式上劃分,線程有兩
 種類(lèi)型:“用戶(hù)級(jí)線程”和“內(nèi)核級(jí)線程”。 用戶(hù)線程指不需要內(nèi)核支持而在用戶(hù)程序
 中實(shí)現(xiàn)的線程,其不依賴(lài)于操作系統(tǒng)核心,應(yīng)用進(jìn)程利用線程庫(kù)提供創(chuàng)建、同步、調(diào)度
 和管理線程的函數(shù)來(lái)控制用戶(hù)線程。這種線程甚至在象 DOS 這樣的操作系統(tǒng)中也可實(shí)現(xiàn)
 ,但線程的調(diào)度需要用戶(hù)程序完成,這有些類(lèi)似 Windows 3.x 的協(xié)作式多任務(wù)。另外一
 種則需要內(nèi)核的參與,由內(nèi)核完成線程的調(diào)度。其依賴(lài)于操作系統(tǒng)核心,由內(nèi)核的內(nèi)部
 需求進(jìn)行創(chuàng)建和撤銷(xiāo),這兩種模型各有其好處和缺點(diǎn)。用戶(hù)線程不需要額外的內(nèi)核開(kāi)支
 ,并且用戶(hù)態(tài)線程的實(shí)現(xiàn)方式可以被定制或修改以適應(yīng)特殊應(yīng)用的要求,但是當(dāng)一個(gè)線
 程因 I/O 而處于等待狀態(tài)時(shí),整個(gè)進(jìn)程就會(huì)被調(diào)度程序切換為等待狀態(tài),其他線程得不
 到運(yùn)行的機(jī)會(huì);而內(nèi)核線程則沒(méi)有各個(gè)限制,有利于發(fā)揮多處理器的并發(fā)優(yōu)勢(shì),但卻占
 用了更多的系統(tǒng)開(kāi)支。
 Windows NT和OS/2支持內(nèi)核線程。Linux 支持內(nèi)核級(jí)的多線程
 
	13.C++中什么數(shù)據(jù)分配在?;蚨阎?,New分配數(shù)據(jù)是在近堆還是遠(yuǎn)堆中?答:棧: 存放局部變量,函數(shù)調(diào)用參數(shù),函數(shù)返回值,函數(shù)返回地址。由系統(tǒng)管理
 堆: 程序運(yùn)行時(shí)動(dòng)態(tài)申請(qǐng),new 和 malloc申請(qǐng)的內(nèi)存就在堆上
 
	14.使用線程是如何防止出現(xiàn)大的波峰。答:意思是如何防止同時(shí)產(chǎn)生大量的線程,方法是使用線程池,線程池具有可以同時(shí)提
 高調(diào)度效率和限制資源使用的好處,線程池中的線程達(dá)到最大數(shù)時(shí),其他線程就會(huì)排隊(duì)
 等候。
 
	15函數(shù)模板與類(lèi)模板有什么區(qū)別?答:函數(shù)模板的實(shí)例化是由編譯程序在處理函數(shù)調(diào)用時(shí)自動(dòng)完成的,而類(lèi)模板的實(shí)例化
 必須由程序員在程序中顯式地指定。
 
	16一般數(shù)據(jù)庫(kù)若出現(xiàn)日志滿(mǎn)了,會(huì)出現(xiàn)什么情況,是否還能使用?答:只能執(zhí)行查詢(xún)等讀操作,不能執(zhí)行更改,備份等寫(xiě)操作,原因是任何寫(xiě)操作都要記
 錄日志。也就是說(shuō)基本上處于不能使用的狀態(tài)。
 
	17 SQL Server是否支持行級(jí)鎖,有什么好處?答:支持,設(shè)立封鎖機(jī)制主要是為了對(duì)并發(fā)操作進(jìn)行控制,對(duì)干擾進(jìn)行封鎖,保證數(shù)據(jù)
 的一致性和準(zhǔn)確性,行級(jí)封鎖確保在用戶(hù)取得被更新的行到該行進(jìn)行更新這段時(shí)間內(nèi)不
 被其它用戶(hù)所修改。因而行級(jí)鎖即可保證數(shù)據(jù)的一致性又能提高數(shù)據(jù)操作的迸發(fā)性。
 
	18如果數(shù)據(jù)庫(kù)滿(mǎn)了會(huì)出現(xiàn)什么情況,是否還能使用?答:見(jiàn)16
 
	19 關(guān)于內(nèi)存對(duì)齊的問(wèn)題以及sizof()的輸出 答:編譯器自動(dòng)對(duì)齊的原因:為了提高程序的性能,數(shù)據(jù)結(jié)構(gòu)(尤其是棧)應(yīng)該盡可能
 地在自然邊界上對(duì)齊。原因在于,為了訪問(wèn)未對(duì)齊的內(nèi)存,處理器需要作兩次內(nèi)存訪問(wèn)
 ;然而,對(duì)齊的內(nèi)存訪問(wèn)僅需要一次訪問(wèn)。
 
	20 int i=10, j=10, k=3; k*=i+j; k最后的值是?答:60,此題考察優(yōu)先級(jí),實(shí)際寫(xiě)成: k*=(i+j);,賦值運(yùn)算符優(yōu)先級(jí)最低
 
	21.對(duì)數(shù)據(jù)庫(kù)的一張表進(jìn)行操作,同時(shí)要對(duì)另一張表進(jìn)行操作,如何實(shí)現(xiàn)?答:將操作多個(gè)表的操作放入到事務(wù)中進(jìn)行處理
 
	22.TCP/IP 建立連接的過(guò)程?(3-way shake)答:在TCP/IP協(xié)議中,TCP協(xié)議提供可靠的連接服務(wù),采用三次握手建立一個(gè)連接。
 第一次握手:建立連接時(shí),客戶(hù)端發(fā)送syn包(syn=j)到服務(wù)器,并進(jìn)入SYN_SEND狀
 態(tài),等待服務(wù)器確認(rèn);
 第二次握手:服務(wù)器收到syn包,必須確認(rèn)客戶(hù)的SYN(ack=j+1),同時(shí)自己也發(fā)送一個(gè)
 SYN包(syn=k),即SYN+ACK包,此時(shí)服務(wù)器進(jìn)入SYN_RECV狀態(tài);
 第三次握手:客戶(hù)端收到服務(wù)器的SYN+ACK包,向服務(wù)器發(fā)送確認(rèn)包ACK(ack=k+1)
 ,此包發(fā)送完畢,客戶(hù)端和服務(wù)器進(jìn)入ESTABLISHED狀態(tài),完成三次握手。
 
	23.ICMP是什么協(xié)議,處于哪一層?答:Internet控制報(bào)文協(xié)議,處于網(wǎng)絡(luò)層(IP層)
 
	24.觸發(fā)器怎么工作的?答:觸發(fā)器主要是通過(guò)事件進(jìn)行觸發(fā)而被執(zhí)行的,當(dāng)對(duì)某一表進(jìn)行諸如UPDATE、 INSERT
 、 DELETE 這些操作時(shí),數(shù)據(jù)庫(kù)就會(huì)自動(dòng)執(zhí)行觸發(fā)器所定義的SQL 語(yǔ)句,從而確保對(duì)數(shù)
 據(jù)的處理必須符合由這些SQL 語(yǔ)句所定義的規(guī)則。
 
	25.winsock建立連接的主要實(shí)現(xiàn)步驟?答:服務(wù)器端:socker()建立套接字,綁定(bind)并監(jiān)聽(tīng)(listen),用accept()
 等待客戶(hù)端連接。
 客戶(hù)端:socker()建立套接字,連接(connect)服務(wù)器,連接上后使用send()和recv(
 ),在套接字上寫(xiě)讀數(shù)據(jù),直至數(shù)據(jù)交換完畢,closesocket()關(guān)閉套接字。
 服務(wù)器端:accept()發(fā)現(xiàn)有客戶(hù)端連接,建立一個(gè)新的套接字,自身重新開(kāi)始等待連
 接。該新產(chǎn)生的套接字使用send()和recv()寫(xiě)讀數(shù)據(jù),直至數(shù)據(jù)交換完畢,closesock
 et()關(guān)閉套接字。
 
	26.動(dòng)態(tài)連接庫(kù)的兩種方式?答:調(diào)用一個(gè)DLL中的函數(shù)有兩種方法:
 1.載入時(shí)動(dòng)態(tài)鏈接(load-time dynamic linking),模塊非常明確調(diào)用某個(gè)導(dǎo)出函數(shù)
 ,使得他們就像本地函數(shù)一樣。這需要鏈接時(shí)鏈接那些函數(shù)所在DLL的導(dǎo)入庫(kù),導(dǎo)入庫(kù)向
 系統(tǒng)提供了載入DLL時(shí)所需的信息及DLL函數(shù)定位。
 2.運(yùn)行時(shí)動(dòng)態(tài)鏈接(run-time dynamic linking),運(yùn)行時(shí)可以通過(guò)LoadLibrary或Loa
 dLibraryEx函數(shù)載入DLL。DLL載入后,模塊可以通過(guò)調(diào)用GetProcAddress獲取DLL函數(shù)的
 出口地址,然后就可以通過(guò)返回的函數(shù)指針調(diào)用DLL函數(shù)了。如此即可避免導(dǎo)入庫(kù)文件了
 。
 
	27.IP組播有那些好處?答:Internet上產(chǎn)生的許多新的應(yīng)用,特別是高帶寬的多媒體應(yīng)用,帶來(lái)了帶寬的急劇
 消耗和網(wǎng)絡(luò)擁擠問(wèn)題。組播是一種允許一個(gè)或多個(gè)發(fā)送者(組播源)發(fā)送單一的數(shù)據(jù)包
 到多個(gè)接收者(一次的,同時(shí)的)的網(wǎng)絡(luò)技術(shù)。組播可以大大的節(jié)省網(wǎng)絡(luò)帶寬,因?yàn)闊o(wú)
 論有多少個(gè)目標(biāo)地址,在整個(gè)網(wǎng)絡(luò)的任何一條鏈路上只傳送單一的數(shù)據(jù)包。所以說(shuō)組播
 技術(shù)的核心就是針對(duì)如何節(jié)約網(wǎng)絡(luò)資源的前提下保證服務(wù)質(zhì)量。
 
	1.static有什么用途?(請(qǐng)至少說(shuō)明兩種)1)在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。
 2) 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問(wèn),但不能被模塊外其它函數(shù)訪問(wèn)。它是一個(gè)本地的全局變量。
 3) 在模塊內(nèi),一個(gè)被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用
 
	2.引用與指針有什么區(qū)別?1) 引用必須被初始化,指針不必。
 2) 引用初始化以后不能被改變,指針可以改變所指的對(duì)象。
 3) 不存在指向空值的引用,但是存在指向空值的指針。
 
	3.描述實(shí)時(shí)系統(tǒng)的基本特性在特定時(shí)間內(nèi)完成特定的任務(wù),實(shí)時(shí)性與可靠性。
 
	4.全局變量和局部變量在內(nèi)存中是否有區(qū)別?如果有,是什么區(qū)別?全局變量?jī)?chǔ)存在靜態(tài)數(shù)據(jù)庫(kù),局部變量在堆棧。
 
	5.什么是平衡二叉樹(shù)?左右子樹(shù)都是平衡二叉樹(shù) 且左右子樹(shù)的深度差值的絕對(duì)值不大于1。
 
	6.堆棧溢出一般是由什么原因?qū)е碌模?br>
      沒(méi)有回收垃圾資源。
 
	7.什么函數(shù)不能聲明為虛函數(shù)?constructor函數(shù)不能聲明為虛函數(shù)。
 
	8.冒泡排序算法的時(shí)間復(fù)雜度是什么?時(shí)間復(fù)雜度是O(n^2)。
 
	9.寫(xiě)出float x 與“零值”比較的if語(yǔ)句。if(x>0.000001&&x<-0.000001)
 
	10.Internet采用哪種網(wǎng)絡(luò)協(xié)議?該協(xié)議的主要層次結(jié)構(gòu)?Tcp/Ip協(xié)議
 主要層次結(jié)構(gòu)為: 應(yīng)用層/傳輸層/網(wǎng)絡(luò)層/數(shù)據(jù)鏈路層/物理層。
 
	11.Internet物理地址和IP地址轉(zhuǎn)換采用什么協(xié)議?ARP (Address Resolution Protocol)(地址解析協(xié)議)
 
	12.IP地址的編碼分為哪倆部分?IP地址由兩部分組成,網(wǎng)絡(luò)號(hào)和主機(jī)號(hào)。不過(guò)是要和“子網(wǎng)掩碼”按位與上之后才能區(qū)分哪些是網(wǎng)絡(luò)位哪些是主機(jī)位。
 
	13.用戶(hù)輸入M,N值,從1至N開(kāi)始順序循環(huán)數(shù)數(shù),每數(shù)到M輸出該數(shù)值,直至全部輸出。寫(xiě)出C程序。循環(huán)鏈表,用取余操作做
 14.不能做switch()的參數(shù)類(lèi)型是:
 switch的參數(shù)不能為實(shí)型。
 
	華為1、局部變量能否和全局變量重名?
 答:能,局部會(huì)屏蔽全局。要用全局變量,需要使用"::"
 局部變量可以與全局變量同名,在函數(shù)內(nèi)引用這個(gè)變量時(shí),會(huì)用到同名的局部變量,而不會(huì)用到全局變量。對(duì)于有些編譯器而言,在同一個(gè)函數(shù)內(nèi)可以定義多個(gè)同名的局部變量,比如在兩個(gè)循環(huán)體內(nèi)都定義一個(gè)同名的局部變量,而那個(gè)局部變量的作用域就在那個(gè)循環(huán)體內(nèi)。
 
	2、如何引用一個(gè)已經(jīng)定義過(guò)的全局變量?答:extern
 可以用引用頭文件的方式,也可以用extern關(guān)鍵字,如果用引用頭文件方式來(lái)引用某個(gè)在頭文件中聲明的全局變理,假定你將那個(gè)變寫(xiě)錯(cuò)了,那么在編譯期間
會(huì)報(bào)錯(cuò),如果你用extern方式引用時(shí),假定你犯了同樣的錯(cuò)誤,那么在編譯期間不會(huì)報(bào)錯(cuò),而在連接期間報(bào)錯(cuò)。
 
	3、全局變量可不可以定義在可被多個(gè).C文件包含的頭文件中?為什么?答:可以,在不同的C文件中以static形式來(lái)聲明同名全局變量。
 可以在不同的C文件中聲明同名的全局變量,前提是其中只能有一個(gè)C文件中對(duì)此變量賦初值,此時(shí)連接不會(huì)出錯(cuò)。
 
	4、語(yǔ)句for( ;1 ;)有什么問(wèn)題?它是什么意思?答:無(wú)限循環(huán),和while(1)相同。
 
	5、do……while和while……do有什么區(qū)別?答:前一個(gè)循環(huán)一遍再判斷,后一個(gè)判斷以后再循環(huán)。
 
	6、請(qǐng)寫(xiě)出下列代碼的輸出內(nèi)容#i nclude
 main()
 {
 int a,b,c,d;
 a=10;
 b=a++;
 c=++a;
 d=10*a++;
 printf("b,c,d:%d,%d,%d",b,c,d);
 return 0;
 }
 答:10,12,120
 
	1、static全局變量與普通的全局變量有什么區(qū)別?static局部變量和普通局部變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?答:全局變量(外部變量)的說(shuō)明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。全局變量本身就是靜態(tài)存儲(chǔ)方式,
靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲(chǔ)方式。 這兩者在存儲(chǔ)方式上并無(wú)不同。這兩者的區(qū)別雖在于非靜態(tài)全局變量的作用域是整個(gè)源程序,
當(dāng)一個(gè)源程序由多個(gè)源文件組成時(shí),非靜態(tài)的全局變量在各個(gè)源文件中都是有效的。 而靜態(tài)全局變量則限制了其作用域, 即只在定義該變量的源文件內(nèi)有效,
在同一源程序的其它源文件中不能使用它。由于靜態(tài)全局變量的作用域局限于一個(gè)源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,
因此可以避免在其它源文件中引起錯(cuò)誤。
 從以上分析可以看出, 把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲(chǔ)方式即改變了它的生存期。把全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域, 限制了它的使用范圍。
 static函數(shù)與普通函數(shù)作用域不同。僅在本文件。只在當(dāng)前源文件中使用的函數(shù)應(yīng)該說(shuō)明為內(nèi)部函數(shù)(static),內(nèi)部函數(shù)應(yīng)該在當(dāng)前源文件中說(shuō)明和定義。對(duì)于可在當(dāng)前源文件以外使用的函數(shù),應(yīng)該在一個(gè)頭文件中說(shuō)明,要使用這些函數(shù)的源文件要包含這個(gè)頭文件
 static全局變量與普通的全局變量有什么區(qū)別:static全局變量只初使化一次,防止在其他文件單元中被引用;
 static局部變量和普通局部變量有什么區(qū)別:static局部變量只被初始化一次,下一次依據(jù)上一次結(jié)果值;
 static函數(shù)與普通函數(shù)有什么區(qū)別:static函數(shù)在內(nèi)存中只有一份,普通函數(shù)在每個(gè)被調(diào)用中維持一份拷貝
 
	2、程序的局部變量存在于(堆棧)中,全局變量存在于(靜態(tài)區(qū) )中,動(dòng)態(tài)申請(qǐng)數(shù)據(jù)存在于( 堆)中。
 
	3、設(shè)有以下說(shuō)明和定義:typedef union {long i; int k[5]; char c;} DATE;
 struct data { int cat; DATE cow; double dog;} too;
 DATE max;
 則語(yǔ)句 printf("%d",sizeof(struct date)+sizeof(max));的執(zhí)行結(jié)果是:___52____
 答:DATE是一個(gè)union, 變量公用空間. 里面最大的變量類(lèi)型是int[5], 占用20個(gè)字節(jié). 所以它的大小是20
 data是一個(gè)struct, 每個(gè)變量分開(kāi)占用空間. 依次為int4 + DATE20 + double8 = 32.
 所以結(jié)果是 20 + 32 = 52.
 當(dāng)然...在某些16位編輯器下, int可能是2字節(jié),那么結(jié)果是 int2 + DATE10 + double8 = 20
 
	4、隊(duì)列和棧有什么區(qū)別?隊(duì)列先進(jìn)先出,棧后進(jìn)先出
 
	5、寫(xiě)出下列代碼的輸出內(nèi)容#i nclude
 int inc(int a)
 {
 return(++a);
 }
 int multi(int*a,int*b,int*c)
 {
 return(*c=*a**b);
 }
 typedef int(FUNC1)(int in);
 typedef int(FUNC2) (int*,int*,int*);
 
	void show(FUNC2 fun,int arg1, int*arg2){
 INCp=&inc;
 int temp =p(arg1);
 fun(&temp,&arg1, arg2);
 printf("%d\n",*arg2);
 }
 
	main(){
 int a;
 show(multi,10,&a);
 return 0;
 }
 答:110
 7、請(qǐng)找出下面代碼中的所以錯(cuò)誤
 說(shuō)明:以下代碼是把一個(gè)字符串倒序,如“abcd”倒序后變?yōu)椤癲cba”
 
	1、#i nclude"string.h"2、main()
 3、{
 4、 char*src="hello,world";
 5、 char* dest=NULL;
 6、 int len=strlen(src);
 7、 dest=(char*)malloc(len);
 8、 char* d=dest;
 9、 char* s=src[len];
 10、 while(len--!=0)
 11、 d++=s--;
 12、 printf("%s",dest);
 13、 return 0;
 14、}
 答:
 方法1:
 int main(){
 char* src = "hello,world";
 int len = strlen(src);
 char* dest = (char*)malloc(len+1);//要為\0分配一個(gè)空間
 char* d = dest;
 char* s = &src[len-1];//指向最后一個(gè)字符
 while( len-- != 0 )
 *d++=*s--;
 *d = 0;//尾部要加\0
 printf("%s\n",dest);
 free(dest);// 使用完,應(yīng)當(dāng)釋放空間,以免造成內(nèi)存匯泄露
 return 0;
 }
 方法2:
 #i nclude
 #i nclude
 main()
 {
 char str[]="hello,world";
 int len=strlen(str);
 char t;
 for(int i=0; i
{
 t=str[i];
 str[i]=str[len-i-1]; str[len-i-1]=t;
 }
 printf("%s",str);
 return 0;
 }
 1.-1,2,7,28,,126請(qǐng)問(wèn)28和126中間那個(gè)數(shù)是什么?為什么?
 第一題的答案應(yīng)該是4^3-1=63
 規(guī)律是n^3-1(當(dāng)n為偶數(shù)0,2,4)
 n^3+1(當(dāng)n為奇數(shù)1,3,5)
 答案:63
 2.用兩個(gè)棧實(shí)現(xiàn)一個(gè)隊(duì)列的功能?要求給出算法和思路!
 設(shè)2個(gè)棧為A,B, 一開(kāi)始均為空.
 
	入隊(duì):將新元素push入棧A;
 
	出隊(duì):(1)判斷棧B是否為空;
 (2)如果不為空,則將棧A中所有元素依次pop出并push到棧B;
 (3)將棧B的棧頂元素pop出;
 
	這樣實(shí)現(xiàn)的隊(duì)列入隊(duì)和出隊(duì)的平攤復(fù)雜度都還是O(1), 比上面的幾種方法要好。3.在c語(yǔ)言庫(kù)函數(shù)中將一個(gè)字符轉(zhuǎn)換成整型的函數(shù)是atool()嗎,這個(gè)函數(shù)的原型是什么?函數(shù)名: atol
 功 能: 把字符串轉(zhuǎn)換成長(zhǎng)整型數(shù)
 用 法: long atol(const char *nptr);
 程序例:
 #i nclude
 #i nclude
 int main(void)
 {
 long l;
 char *str = "98765432";
 
	l = atol(lstr); printf("string = %s integer = %ld\n", str, l);
 return(0);
 }
 
	2.對(duì)于一個(gè)頻繁使用的短小函數(shù),在C語(yǔ)言中應(yīng)用什么實(shí)現(xiàn),在C++中應(yīng)用什么實(shí)現(xiàn)?c用宏定義,c++用inline
 3.直接鏈接兩個(gè)信令點(diǎn)的一組鏈路稱(chēng)作什么?
 PPP點(diǎn)到點(diǎn)連接
 4.接入網(wǎng)用的是什么接口?
 5.voip都用了那些協(xié)議?
 6.軟件測(cè)試都有那些種類(lèi)?
 黑盒:針對(duì)系統(tǒng)功能的測(cè)試    白合:測(cè)試函數(shù)功能,各函數(shù)接口
 7.確定模塊的功能和模塊的接口是在軟件設(shè)計(jì)的那個(gè)隊(duì)段完成的?
 概要設(shè)計(jì)階段
 8.enum string
 {
 x1,
 x2,
 x3=10,
 x4,
 x5,
 }x;
 問(wèn)x= 0x801005,0x8010f4  ;
 9.unsigned char *p1;
 unsigned long *p2;
 p1=(unsigned char *)0x801000;
 p2=(unsigned long *)0x810000;
 請(qǐng)問(wèn)p1+5=  ;
 p2+5=  ;
 三.選擇題:
 1.Ethternet鏈接到Internet用到以下那個(gè)協(xié)議?
 A.HDLC;B.ARP;C.UDP;D.TCP;E.ID
 2.屬于網(wǎng)絡(luò)層協(xié)議的是:
 A.TCP;B.IP;C.ICMP;D.X.25
 3.Windows消息調(diào)度機(jī)制是:
 A.指令隊(duì)列;B.指令堆棧;C.消息隊(duì)列;D.消息堆棧;
 4.unsigned short hash(unsigned short key)
 {
 return (key>>)%256
 }
 請(qǐng)問(wèn)hash(16),hash(256)的值分別是:
 A.1.16;B.8.32;C.4.16;D.1.32
 四.找錯(cuò)題:
 1.請(qǐng)問(wèn)下面程序有什么錯(cuò)誤?
 int a[60][250][1000],i,j,k;
 for(k=0;k<=1000;k++)
 for(j=0;j<250;j++)
 for(i=0;i<60;i++)
 a[i][j][k]=0;
 把循環(huán)語(yǔ)句內(nèi)外換一下
 2.#define Max_CB 500
 void LmiQueryCSmd(Struct MSgCB * pmsg)
 {
 unsigned char ucCmdNum;
 ......
 
 for(ucCmdNum=0;ucCmdNum
      {
 ......;
 }
 死循環(huán)
 3.以下是求一個(gè)數(shù)的平方的程序,請(qǐng)找出錯(cuò)誤:
 #define SQUARE(a)((a)*(a))
 int a=5;
 int b;
 b=SQUARE(a++);
 4.typedef unsigned char BYTE
 int examply_fun(BYTE gt_len; BYTE *gt_code)
 {
 BYTE *gt_buf;
 gt_buf=(BYTE *)MALLOC(Max_GT_Length);
 ......
 if(gt_len>Max_GT_Length)
 {
 return GT_Length_ERROR;
 }
 .......
 }
 五.問(wèn)答題:
 1.IP Phone的原理是什么?
 IPV6
 2.TCP/IP通信建立的過(guò)程怎樣,端口有什么作用?
 三次握手,確定是哪個(gè)應(yīng)用程序使用該協(xié)議
 3.1號(hào)信令和7號(hào)信令有什么區(qū)別,我國(guó)某前廣泛使用的是那一種?
 4.列舉5種以上的電話(huà)新業(yè)務(wù)?
 
	微軟亞洲技術(shù)中心的面試題!??!1.進(jìn)程和線程的差別。
 線程是指進(jìn)程內(nèi)的一個(gè)執(zhí)行單元,也是進(jìn)程內(nèi)的可調(diào)度實(shí)體.
 與進(jìn)程的區(qū)別:
 (1)調(diào)度:線程作為調(diào)度和分配的基本單位,進(jìn)程作為擁有資源的基本單位
 (2)并發(fā)性:不僅進(jìn)程之間可以并發(fā)執(zhí)行,同一個(gè)進(jìn)程的多個(gè)線程之間也可并發(fā)執(zhí)行
 (3)擁有資源:進(jìn)程是擁有資源的一個(gè)獨(dú)立單位,線程不擁有系統(tǒng)資源,但可以訪問(wèn)隸屬于進(jìn)程的資源.
 (4)系統(tǒng)開(kāi)銷(xiāo):在創(chuàng)建或撤消進(jìn)程時(shí),由于系統(tǒng)都要為之分配和回收資源,導(dǎo)致系統(tǒng)的開(kāi)銷(xiāo)明顯大于創(chuàng)建或撤消線程時(shí)的開(kāi)銷(xiāo)。
 2.測(cè)試方法
 人工測(cè)試:個(gè)人復(fù)查、抽查和會(huì)審
 機(jī)器測(cè)試:黑盒測(cè)試和白盒測(cè)試
 
	2.Heap與stack的差別。Heap是堆,stack是棧。
 Stack的空間由操作系統(tǒng)自動(dòng)分配/釋放,Heap上的空間手動(dòng)分配/釋放。
 Stack空間有限,Heap是很大的自由存儲(chǔ)區(qū)
 C中的malloc函數(shù)分配的內(nèi)存空間即在堆上,C++中對(duì)應(yīng)的是new操作符。
 程序在編譯期對(duì)變量和函數(shù)分配內(nèi)存都在棧上進(jìn)行,且程序運(yùn)行過(guò)程中函數(shù)調(diào)用時(shí)參數(shù)的傳遞也在棧上進(jìn)行
 3.Windows下的內(nèi)存是如何管理的?
 4.介紹.Net和.Net的安全性。
 5.客戶(hù)端如何訪問(wèn).Net組件實(shí)現(xiàn)Web Service?
 6.C/C++編譯器中虛表是如何完成的?
 7.談?wù)凜OM的線程模型。然后討論進(jìn)程內(nèi)/外組件的差別。
 8.談?wù)処A32下的分頁(yè)機(jī)制
 小頁(yè)(4K)兩級(jí)分頁(yè)模式,大頁(yè)(4M)一級(jí)
 9.給兩個(gè)變量,如何找出一個(gè)帶環(huán)單鏈表中是什么地方出現(xiàn)環(huán)的?
 一個(gè)遞增一,一個(gè)遞增二,他們指向同一個(gè)接點(diǎn)時(shí)就是環(huán)出現(xiàn)的地方
 10.在IA32中一共有多少種辦法從用戶(hù)態(tài)跳到內(nèi)核態(tài)?
 通過(guò)調(diào)用門(mén),從ring3到ring0,中斷從ring3到ring0,進(jìn)入vm86等等
 11.如果只想讓程序有一個(gè)實(shí)例運(yùn)行,不能運(yùn)行兩個(gè)。像winamp一樣,只能開(kāi)一個(gè)窗口,怎樣實(shí)現(xiàn)?
 用內(nèi)存映射或全局原子(互斥變量)、查找窗口句柄..
 FindWindow,互斥,寫(xiě)標(biāo)志到文件或注冊(cè)表,共享內(nèi)存。.
 12.如何截取鍵盤(pán)的響應(yīng),讓所有的‘a(chǎn)’變成‘b’?
 鍵盤(pán)鉤子SetWindowsHookEx
 13.Apartment在COM中有什么用?為什么要引入?
 14.存儲(chǔ)過(guò)程是什么?有什么用?有什么優(yōu)點(diǎn)?
 我的理解就是一堆sql的集合,可以建立非常復(fù)雜的查詢(xún),編譯運(yùn)行,所以運(yùn)行一次后,以后再運(yùn)行速度比單獨(dú)執(zhí)行SQL快很多
 15.Template有什么特點(diǎn)?什么時(shí)候用?
 16.談?wù)刉indows DNA結(jié)構(gòu)的特點(diǎn)和優(yōu)點(diǎn)。
 
	網(wǎng)絡(luò)編程中設(shè)計(jì)并發(fā)服務(wù)器,使用多進(jìn)程 與 多線程 ,請(qǐng)問(wèn)有什么區(qū)別?
 1,進(jìn)程:子進(jìn)程是父進(jìn)程的復(fù)制品。子進(jìn)程獲得父進(jìn)程數(shù)據(jù)空間、堆和棧的復(fù)制品。
 2,線程:相對(duì)與進(jìn)程而言,線程是一個(gè)更加接近與執(zhí)行體的概念,它可以與同進(jìn)程的其他線程共享數(shù)據(jù),但擁有自己的??臻g,擁有獨(dú)立的執(zhí)行序列。
 兩者都可以提高程序的并發(fā)度,提高程序運(yùn)行效率和響應(yīng)時(shí)間。
 線程和進(jìn)程在使用上各有優(yōu)缺點(diǎn):線程執(zhí)行開(kāi)銷(xiāo)小,但不利于資源管理和保護(hù);而進(jìn)程正相反。同時(shí),線程適合于在SMP機(jī)器上運(yùn)行,而進(jìn)程則可以跨機(jī)器遷移。
 
	思科1. 用宏定義寫(xiě)出swap(x,y)
 #define swap(x, y)\
 x = x + y;\
 y = x - y;\
 x = x - y;
 2.數(shù)組a[N],存放了1至N-1個(gè)數(shù),其中某個(gè)數(shù)重復(fù)一次。寫(xiě)一個(gè)函數(shù),找出被重復(fù)的數(shù)字.時(shí)間復(fù)雜度必須為o(N)函數(shù)原型:
 int do_dup(int a[],int N)
 3 一語(yǔ)句實(shí)現(xiàn)x是否為2的若干次冪的判斷
 int i = 512;
 cout << boolalpha << ((i & (i - 1)) ? false : true) << endl;
 4.unsigned int intvert(unsigned int x,int p,int n)實(shí)現(xiàn)對(duì)x的進(jìn)行轉(zhuǎn)換,p為起始轉(zhuǎn)化位,n為需要轉(zhuǎn)換的長(zhǎng)度,假設(shè)起始點(diǎn)在右邊.如x=0b0001 0001,p=4,n=3轉(zhuǎn)換后x=0b0110 0001
 unsigned int intvert(unsigned int x,int p,int n){
 unsigned int _t = 0;
 unsigned int _a = 1;
 for(int i = 0; i < n; ++i){
 _t |= _a;
 _a = _a << 1;
 }
 _t = _t << p;
 x ^= _t;
 return x;
 }
 
	慧通:什么是預(yù)編譯
 何時(shí)需要預(yù)編譯:
 1、總是使用不經(jīng)常改動(dòng)的大型代碼體。
 2、程序由多個(gè)模塊組成,所有模塊都使用一組標(biāo)準(zhǔn)的包含文件和相同的編譯選項(xiàng)。在這種情況下,可以將所有包含文件預(yù)編譯為一個(gè)預(yù)編譯頭。
 char * const p;
 char const * p
 const char *p
 
	上述三個(gè)有什么區(qū)別?char * const p; //常量指針,p的值不可以修改
 char const * p;//指向常量的指針,指向的常量值不可以改
 const char *p; //和char const *p
 
	char str1[] = "abc";char str2[] = "abc";
 
	const char str3[] = "abc";const char str4[] = "abc";
 
	const char *str5 = "abc";const char *str6 = "abc";
 
	char *str7 = "abc";char *str8 = "abc";
 
	cout << ( str1 == str2 ) << endl;
 cout << ( str3 == str4 ) << endl;
 cout << ( str5 == str6 ) << endl;
 cout << ( str7 == str8 ) << endl;
 
	結(jié)果是:0 0 1 1解答:str1,str2,str3,str4是數(shù)組變量,它們有各自的內(nèi)存空間;
 而str5,str6,str7,str8是指針,它們指向相同的常量區(qū)域。
 
	12. 以下代碼中的兩個(gè)sizeof用法有問(wèn)題嗎?[C易]
 void UpperCase( char str[] ) // 將 str 中的小寫(xiě)字母轉(zhuǎn)換成大寫(xiě)字母
 {
 for( size_t i=0; i
        if( 'a'<=str[i] && str[i]<='z' )
 str[i] -= ('a'-'A' );
 }
 char str[] = "aBcDe";
 cout << "str字符長(zhǎng)度為: " << sizeof(str)/sizeof(str[0]) << endl;
 UpperCase( str );
 cout << str << endl;
 
	答:函數(shù)內(nèi)的sizeof有問(wèn)題。根據(jù)語(yǔ)法,sizeof如用于數(shù)組,只能測(cè)出靜態(tài)數(shù)組的大小,無(wú)法
檢測(cè)動(dòng)態(tài)分配的或外部數(shù)組大小。函數(shù)外的str是一個(gè)靜態(tài)定義的數(shù)組,因此其大小為6,函數(shù)內(nèi)的str實(shí)際只是一個(gè)指向字符串的指針,沒(méi)有任何額外的與數(shù)
組相關(guān)的信息,因此sizeof作用于上只將其當(dāng)指針看,一個(gè)指針為4個(gè)字節(jié),因此返回4。
 
	一個(gè)32位的機(jī)器,該機(jī)器的指針是多少位指針是多少位只要看地址總線的位數(shù)就行了。80386以后的機(jī)子都是32的數(shù)據(jù)總線。所以指針的位數(shù)就是4個(gè)字節(jié)了。
 
	main(){
 int a[5]={1,2,3,4,5};
 int *ptr=(int *)(&a+1);
 
	   printf("%d,%d",*(a+1),*(ptr-1));}
 輸出:2,5
 *(a+1)就是a[1],*(ptr-1)就是a[4],執(zhí)行結(jié)果是2,5
 &a+1不是首地址+1,系統(tǒng)會(huì)認(rèn)為加一個(gè)a數(shù)組的偏移,是偏移了一個(gè)數(shù)組的大?。ū纠?個(gè)int)
 int *ptr=(int *)(&a+1);
 則ptr實(shí)際是&(a[5]),也就是a+5
 原因如下:
 &a是數(shù)組指針,其類(lèi)型為 int (*)[5];
 而指針加1要根據(jù)指針類(lèi)型加上一定的值,
 不同類(lèi)型的指針+1之后增加的大小不同
 a是長(zhǎng)度為5的int數(shù)組指針,所以要加 5*sizeof(int)
 所以ptr實(shí)際是a[5]
 但是prt與(&a+1)類(lèi)型是不一樣的(這點(diǎn)很重要)
 所以prt-1只會(huì)減去sizeof(int*)
 a,&a的地址是一樣的,但意思不一樣,a是數(shù)組首地址,也就是a[0]的地址,&a是對(duì)象(數(shù)組)首地址,a+1是數(shù)組下一元素的地址,即a[1],&a+1是下一個(gè)對(duì)象的地址,即a[5].
 
	1.請(qǐng)問(wèn)以下代碼有什么問(wèn)題:
 int  main()
 {
 char a;
 char *str=&a;
 strcpy(str,"hello");
 printf(str);
 return 0;
 }
 沒(méi)有為str分配內(nèi)存空間,將會(huì)發(fā)生異常
 問(wèn)題出在將一個(gè)字符串復(fù)制進(jìn)一個(gè)字符變量指針?biāo)傅刂贰km然可以正確輸出結(jié)果,但因?yàn)樵浇邕M(jìn)行內(nèi)在讀寫(xiě)而導(dǎo)致程序崩潰。
 
	char* s="AAA";printf("%s",s);
 s[0]='B';
 printf("%s",s);
 有什么錯(cuò)?
 "AAA"是字符串常量。s是指針,指向這個(gè)字符串常量,所以聲明s的時(shí)候就有問(wèn)題。
 cosnt char* s="AAA";
 然后又因?yàn)槭浅A?,所以?duì)是s[0]的賦值操作是不合法的。
 
	1、寫(xiě)一個(gè)“標(biāo)準(zhǔn)”宏,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。.#define Min(X, Y) ((X)>(Y)?(Y):(X))//結(jié)尾沒(méi)有;
 2、嵌入式系統(tǒng)中經(jīng)常要用到無(wú)限循環(huán),你怎么用C編寫(xiě)死循環(huán)。
 while(1){}或者for(;;)
 3、關(guān)鍵字static的作用是什么?
 定義靜態(tài)變量
 4、關(guān)鍵字const有什么含意?
 表示常量不可以修改的變量。
 5、關(guān)鍵字volatile有什么含意?并舉出三個(gè)不同的例子?
 提示編譯器對(duì)象的值可能在編譯器未監(jiān)測(cè)到的情況下改變。
 
	int (*s[10])(int) 表示的是什么啊
 int (*s[10])(int) 函數(shù)指針數(shù)組,每個(gè)指針指向一個(gè)int func(int param)的函數(shù)。
 
	1.有以下表達(dá)式:
 int a=248; b=4;int const c=21;const int *d=&a;
 int *const e=&b;int const *f const =&a;
 請(qǐng)問(wèn)下列表達(dá)式哪些會(huì)被編譯器禁止?為什么?
 *c=32;d=&b;*d=43;e=34;e=&a;f=0x321f;
 *c 這是個(gè)什么東東,禁止
 *d 說(shuō)了是const, 禁止
 e = &a 說(shuō)了是const 禁止
 const *f const =&a; 禁止
 2.交換兩個(gè)變量的值,不使用第三個(gè)變量。即a=3,b=5,交換之后a=5,b=3;
 有兩種解法, 一種用算術(shù)算法, 一種用^(異或)
 a = a + b;
 b = a - b;
 a = a - b;
 or
 a = a^b;// 只能對(duì)int,char..
 b = a^b;
 a = a^b;
 or
 a ^= b ^= a;
 3.c和c++中的struct有什么不同?
 c和c++中struct的主要區(qū)別是c中的struct不可以含有成員函數(shù),而c++中的struct可以。c++中struct和class的主要區(qū)別在于默認(rèn)的存取權(quán)限不同,struct默認(rèn)為public,而class默認(rèn)為private
 4.#i nclude
 #i nclude
 void getmemory(char *p)
 {
 p=(char *) malloc(100);
 strcpy(p,"hello world");
 }
 int main( )
 {
 char *str=NULL;
 getmemory(str);
 printf("%s/n",str);
 free(str);
 return 0;
 }
 程序崩潰,getmemory中的malloc 不能返回動(dòng)態(tài)內(nèi)存, free()對(duì)str操作很危險(xiǎn)
 5.char szstr[10];
 strcpy(szstr,"0123456789");
 產(chǎn)生什么結(jié)果?為什么?
 長(zhǎng)度不一樣,會(huì)造成非法的OS
 6.列舉幾種進(jìn)程的同步機(jī)制,并比較其優(yōu)缺點(diǎn)。
 原子操作
 信號(hào)量機(jī)制
 自旋鎖
 管程,會(huì)合,分布式系統(tǒng)
 
	7.進(jìn)程之間通信的途徑共享存儲(chǔ)系統(tǒng)
 消息傳遞系統(tǒng)
 管道:以文件系統(tǒng)為基礎(chǔ)
 11.進(jìn)程死鎖的原因
 資源競(jìng)爭(zhēng)及進(jìn)程推進(jìn)順序非法
 12.死鎖的4個(gè)必要條件
 互斥、請(qǐng)求保持、不可剝奪、環(huán)路
 13.死鎖的處理
 鴕鳥(niǎo)策略、預(yù)防策略、避免策略、檢測(cè)與解除死鎖
 15.   操作系統(tǒng)中進(jìn)程調(diào)度策略有哪幾種?
 FCFS(先來(lái)先服務(wù)),優(yōu)先級(jí),時(shí)間片輪轉(zhuǎn),多級(jí)反饋
 8.類(lèi)的靜態(tài)成員和非靜態(tài)成員有何區(qū)別?
 類(lèi)的靜態(tài)成員每個(gè)類(lèi)只有一個(gè),非靜態(tài)成員每個(gè)對(duì)象一個(gè)
 9.純虛函數(shù)如何定義?使用時(shí)應(yīng)注意什么?
 virtual void f()=0;
 是接口,子類(lèi)必須要實(shí)現(xiàn)
 10.數(shù)組和鏈表的區(qū)別
 數(shù)組:數(shù)據(jù)順序存儲(chǔ),固定大小
 連表:數(shù)據(jù)可以隨機(jī)存儲(chǔ),大小可動(dòng)態(tài)改變
 
	12.ISO的七層模型是什么?tcp/udp是屬于哪一層?tcp/udp有何優(yōu)缺點(diǎn)?應(yīng)用層
 表示層
 會(huì)話(huà)層
 運(yùn)輸層
 網(wǎng)絡(luò)層
 物理鏈路層
 物理層
 tcp /udp屬于運(yùn)輸層
 TCP 服務(wù)提供了數(shù)據(jù)流傳輸、可靠性、有效流控制、全雙工操作和多路復(fù)用技術(shù)等。
 與 TCP 不同, UDP 并不提供對(duì) IP 協(xié)議的可靠機(jī)制、流控制以及錯(cuò)誤恢復(fù)功能等。由于 UDP 比較簡(jiǎn)單, UDP 頭包含很少的字節(jié),比 TCP 負(fù)載消耗少。
 tcp: 提供穩(wěn)定的傳輸服務(wù),有流量控制,缺點(diǎn)是包頭大,冗余性不好
 udp: 不提供穩(wěn)定的服務(wù),包頭小,開(kāi)銷(xiāo)小
 
	1:(void *)ptr 和 (*(void**))ptr的結(jié)果是否相同?其中ptr為同一個(gè)指針
 .(void *)ptr 和 (*(void**))ptr值是相同的
 2:int main()
 {
 int x=3;
 printf("%d",x);
 return 1;
 
 }
 問(wèn)函數(shù)既然不會(huì)被其它函數(shù)調(diào)用,為什么要返回1?
 mian中,c標(biāo)準(zhǔn)認(rèn)為0表示成功,非0表示錯(cuò)誤。具體的值是某中具體出錯(cuò)信息
 
	1,要對(duì)絕對(duì)地址0x100000賦值,我們可以用
 (unsigned int*)0x100000 = 1234;
 那么要是想讓程序跳轉(zhuǎn)到絕對(duì)地址是0x100000去執(zhí)行,應(yīng)該怎么做?
 *((void (*)( ))0x100000 ) ( );
 首先要將0x100000強(qiáng)制轉(zhuǎn)換成函數(shù)指針,即:
 (void (*)())0x100000
 然后再調(diào)用它:
 *((void (*)())0x100000)();
 用typedef可以看得更直觀些:
 typedef void(*)() voidFuncPtr;
 *((voidFuncPtr)0x100000)();
 2,已知一個(gè)數(shù)組table,用一個(gè)宏定義,求出數(shù)據(jù)的元素個(gè)數(shù)
 #define NTBL
 #define NTBL (sizeof(table)/sizeof(table[0]))
 
	面試題: 線程與進(jìn)程的區(qū)別和聯(lián)系? 線程是否具有相同的堆棧? dll是否有獨(dú)立的堆棧?進(jìn)程是死的,只是一些資源的集合,真正的程序執(zhí)行都是線程來(lái)完成的,程序啟動(dòng)的時(shí)候操作系統(tǒng)就幫你創(chuàng)建了一個(gè)主線程。
 
	每個(gè)線程有自己的堆棧。DLL中有沒(méi)有獨(dú)立的堆棧,這個(gè)問(wèn)題不好回答,或者說(shuō)這個(gè)問(wèn)題本身是
否有問(wèn)題。因?yàn)镈LL中的代碼是被某些線程所執(zhí)行,只有線程擁有堆棧,如果DLL中的代碼是EXE中的線程所調(diào)用,那么這個(gè)時(shí)候是不是說(shuō)這個(gè)DLL沒(méi)有自
己獨(dú)立的堆棧?如果DLL中的代碼是由DLL自己創(chuàng)建的線程所執(zhí)行,那么是不是說(shuō)DLL有獨(dú)立的堆棧?
 
	以上講的是堆棧,如果對(duì)于堆來(lái)說(shuō),每個(gè)DLL有自己的堆,所以如果是從DLL中動(dòng)態(tài)分配的內(nèi)存,最好是從DLL中刪除,如果你從DLL中分配內(nèi)存,然后在EXE中,或者另外一個(gè)DLL中刪除,很有可能導(dǎo)致程序崩潰
 
	unsigned short A = 10;
 printf("~A = %u\n", ~A);
 
	char c=128; printf("c=%d\n",c);
 
	輸出多少?并分析過(guò)程第一題,~A =0xfffffff5,int值 為-11,但輸出的是uint。所以輸出4294967285
 第二題,c=0x10,輸出的是int,最高位為1,是負(fù)數(shù),所以它的值就是0x00的補(bǔ)碼就是128,所以輸出-128。
 這兩道題都是在考察二進(jìn)制向int或uint轉(zhuǎn)換時(shí)的最高位處理。
 
	分析下面的程序:void GetMemory(char **p,int num)
 {
 *p=(char *)malloc(num);
 
 }
 int main()
 {
 char *str=NULL;
 
 GetMemory(&str,100);
 
 strcpy(str,"hello");
 
 free(str);
 
 if(str!=NULL)
 {
 strcpy(str,"world");
 }
 
 printf("\n str is %s",str);
 getchar();
 }
 問(wèn)輸出結(jié)果是什么?希望大家能說(shuō)說(shuō)原因,先謝謝了
 輸出str is world。
 free 只是釋放的str指向的內(nèi)存空間,它本身的值還是存在的.
 所以free之后,有一個(gè)好的習(xí)慣就是將str=NULL.
 此時(shí)str指向空間的內(nèi)存已被回收,如果輸出語(yǔ)句之前還存在分配空間的操作的話(huà),這段存儲(chǔ)空間是可能被重新分配給其他變量的,
 盡管這段程序確實(shí)是存在大大的問(wèn)題(上面各位已經(jīng)說(shuō)得很清楚了),但是通常會(huì)打印出world來(lái)。
 這是因?yàn)?,進(jìn)程中的內(nèi)存管理一般不是由操作系統(tǒng)完成的,而是由庫(kù)函數(shù)自己完成的。
 當(dāng)
你malloc一塊內(nèi)存的時(shí)候,管理庫(kù)向操作系統(tǒng)申請(qǐng)一塊空間(可能會(huì)比你申請(qǐng)的大一些),然后在這塊空間中記錄一些管理信息(一般是在你申請(qǐng)的內(nèi)存前面
一點(diǎn)),并將可用內(nèi)存的地址返回。但是釋放內(nèi)存的時(shí)候,管理庫(kù)通常都不會(huì)將內(nèi)存還給操作系統(tǒng),因此你是可以繼續(xù)訪問(wèn)這塊地址的,只不過(guò)。。。。。。。。樓
上都說(shuō)過(guò)了,最好別這么干。
 
	char a[10],strlen(a)為什么等于15?運(yùn)行的結(jié)果
 
	#i nclude "stdio.h"#i nclude "string.h"
 
	void main(){
 
	char aa[10];printf("%d",strlen(aa));
 }
 
	sizeof()和初不初始化,沒(méi)有關(guān)系;strlen()和初始化有關(guān)。
 
	char (*str)[20];/*str是一個(gè)數(shù)組指針,即指向數(shù)組的指針.*/
 char *str[20];/*str是一個(gè)指針數(shù)組,其元素為指針型數(shù)據(jù).*/
 
	long a=0x801010;a+5=?
 0x801010用二進(jìn)制表示為:“1000 0000 0001 0000 0001 0000”,十進(jìn)制的值為8392720,再加上5就是8392725羅
 
	1)給定結(jié)構(gòu)struct A {
 char t:4;
 char k:4;
 unsigned short i:8;
 unsigned long m;
 };問(wèn)sizeof(A) = ?
 給定結(jié)構(gòu)struct A
 {
 char t:4; 4位
 char k:4; 4位
 unsigned short i:8; 8位
 unsigned long m; // 偏移2字節(jié)保證4字節(jié)對(duì)齊
 }; // 共8字節(jié)
 2)下面的函數(shù)實(shí)現(xiàn)在一個(gè)數(shù)上加一個(gè)數(shù),有什么錯(cuò)誤?請(qǐng)改正。
 int add_n ( int n )
 {
 static int i = 100;
 i += n;
 return i;
 }
 當(dāng)你第二次調(diào)用時(shí)得不到正確的結(jié)果,難道你寫(xiě)個(gè)函數(shù)就是為了調(diào)用一次?問(wèn)題就出在 static上?
 
	// 幫忙分析一下
 #i nclude
 #i nclude
 #i nclude
 #i nclude
 #i nclude
 #i nclude
 typedef struct  AA
 {
 int b1:5;
 int b2:2;
 }AA;
 void main()
 {
 AA aa;
 char cc[100];
 strcpy(cc,"0123456789abcdefghijklmnopqrstuvwxyz");
 memcpy(&aa,cc,sizeof(AA));
 cout << aa.b1 <
        cout << aa.b2 <
}
 答案是 -16和1
 首先sizeof(AA)的大小為4,b1和b2分別占5bit和2bit.
 經(jīng)過(guò)strcpy和memcpy后,aa的4個(gè)字節(jié)所存放的值是:
 0,1,2,3的ASC碼,即00110000,00110001,00110010,00110011
 所以,最后一步:顯示的是這4個(gè)字節(jié)的前5位,和之后的2位
 分別為:10000,和01
 因?yàn)閕nt是有正負(fù)之分  所以:答案是-16和1
 
	求函數(shù)返回值,輸入x=9999; int func ( x )
 {
 int countx = 0;
 while ( x )
 {
 countx ++;
 x = x&(x-1);
 }
 return countx;
 }
 結(jié)果呢?
 知道了這是統(tǒng)計(jì)9999的二進(jìn)制數(shù)值中有多少個(gè)1的函數(shù),且有
 9999=9×1024+512+256+15
 
	9×1024中含有1的個(gè)數(shù)為2;512中含有1的個(gè)數(shù)為1;
 256中含有1的個(gè)數(shù)為1;
 15中含有1的個(gè)數(shù)為4;
 故共有1的個(gè)數(shù)為8,結(jié)果為8。
 1000 - 1 = 0111,正好是原數(shù)取反。這就是原理。
 用這種方法來(lái)求1的個(gè)數(shù)是很效率很高的。
 不必去一個(gè)一個(gè)地移位。循環(huán)次數(shù)最少。
 
	int a,b,c 請(qǐng)寫(xiě)函數(shù)實(shí)現(xiàn)C=a+b ,不可以改變數(shù)據(jù)類(lèi)型,如將c改為long int,關(guān)鍵是如何處理溢出問(wèn)題bool add (int a, int b,int *c)
 {
 *c=a+b;
 return (a>0 && b>0 &&(*ca || *c>b)));
 }
 
	分析:
 struct bit
 {   int a:3;
 int  b:2;
 int c:3;
 };
 int main()
 {
 bit s;
 char *c=(char*)&s;
 cout<
  *c=0x99;
 cout << s.a <
     int a=-1;
 printf("%x",a);
 return 0;
 }
 輸出為什么是
 4
 1
 -1
 -4
 ffffffff
 因?yàn)?x99在內(nèi)存中表示為 100 11 001 , a = 001, b = 11, c = 100
 當(dāng)c為有符合數(shù)時(shí), c = 100, 最高1為表示c為負(fù)數(shù),負(fù)數(shù)在計(jì)算機(jī)用補(bǔ)碼表示,所以c = -4;同理
 b = -1;
 當(dāng)c為有符合數(shù)時(shí), c = 100,即 c = 4,同理 b = 3
 
	位域 :
 有些信息在存儲(chǔ)時(shí),并不需要占用一個(gè)完整的字節(jié),
而只需占幾個(gè)或一個(gè)二進(jìn)制位。例如在存放一個(gè)開(kāi)關(guān)量時(shí),只有0和1 兩種狀態(tài),
用一位二進(jìn)位即可。為了節(jié)省存儲(chǔ)空間,并使處理簡(jiǎn)便,C語(yǔ)言又提供了一種數(shù)據(jù)結(jié)構(gòu),稱(chēng)為“位域”或“位段”。所謂“位域”是把一個(gè)字節(jié)中的二進(jìn)位劃分為幾
個(gè)不同的區(qū)域, 并說(shuō)明每個(gè)區(qū)域的位數(shù)。每個(gè)域有一個(gè)域名,允許在程序中按域名進(jìn)行操作。
這樣就可以把幾個(gè)不同的對(duì)象用一個(gè)字節(jié)的二進(jìn)制位域來(lái)表示。一、位域的定義和位域變量的說(shuō)明位域定義與結(jié)構(gòu)定義相仿,其形式為:
 struct 位域結(jié)構(gòu)名
 { 位域列表 };
 其中位域列表的形式為: 類(lèi)型說(shuō)明符 位域名:位域長(zhǎng)度
 例如:
 struct bs
 {
 int a:8;
 int b:2;
 int c:6;
 };
 位域變量的說(shuō)明與結(jié)構(gòu)變量說(shuō)明的方式相同。 可采用先定義后說(shuō)明,同時(shí)定義說(shuō)明或者直接說(shuō)明這三種方式。例如:
 struct bs
 {
 int a:8;
 int b:2;
 int c:6;
 }data;
 說(shuō)明data為bs變量,共占兩個(gè)字節(jié)。其中位域a占8位,位域b占2位,位域c占6位。對(duì)于位域的定義尚有以下幾點(diǎn)說(shuō)明:
 
	1. 一個(gè)位域必須存儲(chǔ)在同一個(gè)字節(jié)中,不能跨兩個(gè)字節(jié)。如一個(gè)字節(jié)所剩空間不夠存放另一位域時(shí),應(yīng)從下一單元起存放該位域。也可以有意使某位域從下一單元開(kāi)始。例如:     struct bs
 {
 unsigned a:4
 unsigned :0 /*空域*/
 unsigned b:4 /*從下一單元開(kāi)始存放*/
 unsigned c:4
 }
 在這個(gè)位域定義中,a占第一字節(jié)的4位,后4位填0表示不使用,b從第二字節(jié)開(kāi)始,占用4位,c占用4位。
 
	2. 由于位域不允許跨兩個(gè)字節(jié),因此位域的長(zhǎng)度不能大于一個(gè)字節(jié)的長(zhǎng)度,也就是說(shuō)不能超過(guò)8位二進(jìn)位。    
 
	3. 位域可以無(wú)位域名,這時(shí)它只用來(lái)作填充或調(diào)整位置。無(wú)名的位域是不能使用的。例如:     struct k
 {
 int a:1
 int :2 /*該2位不能使用*/
 int b:3
 int c:2
 };
 從以上分析可以看出,位域在本質(zhì)上就是一種結(jié)構(gòu)類(lèi)型, 不過(guò)其成員是按二進(jìn)位分配的。
 
	二、位域的使用位域的使用和結(jié)構(gòu)成員的使用相同,其一般形式為: 位域變量名·位域名 位域允許用各種格式輸出。    main(){
 struct bs
 {
 unsigned a:1;
 unsigned b:3;
 unsigned c:4;
 } bit,*pbit;
 bit.a=1;
 bit.b=7;
 bit.c=15;
 pri
 
	改錯(cuò):#i nclude
 
	int main(void) {
 
	    int **p;int arr[100];
 
	    p = &arr;
 
	    return 0;}
 解答:
 搞錯(cuò)了,是指針類(lèi)型不同,
 int **p; //二級(jí)指針
 &arr; //得到的是指向第一維為100的數(shù)組的指針
 #i nclude
 int main(void) {
 int **p, *q;
 int arr[100];
 q = arr;
 p = &q;
 return 0;
 }
 
	下面這個(gè)程序執(zhí)行后會(huì)有什么錯(cuò)誤或者效果:
 #define MAX 255
 int main()
 {
 unsigned char A[MAX],i;//i被定義為unsigned char
 for (i=0;i<=MAX;i++)
 A[i]=i;
 }
 解答:死循環(huán)加數(shù)組越界訪問(wèn)(C/C++不進(jìn)行數(shù)組越界檢查)
 MAX=255
 數(shù)組A的下標(biāo)范圍為:0..MAX-1,這是其一..
 其二.當(dāng)i循環(huán)到255時(shí),循環(huán)內(nèi)執(zhí)行:
 A[255]=255;
 這句本身沒(méi)有問(wèn)題..但是返回for (i=0;i<=MAX;i++)語(yǔ)句時(shí),
 由于unsigned char的取值范圍在(0..255),i++以后i又為0了..無(wú)限循環(huán)下去.
 
	struct name1{char  str;
 short x;
 int   num;
 }
 
	struct name2{char str;
 int num;
 short x;
 }
 
	sizeof(struct name1)=8,sizeof(struct name2)=12在第二個(gè)結(jié)構(gòu)中,為保證num按四個(gè)字節(jié)對(duì)齊,char后必須留出3字節(jié)的空間;同時(shí)為保證整個(gè)結(jié)構(gòu)的自然對(duì)齊(這里是4字節(jié)對(duì)齊),在x后還要補(bǔ)齊2個(gè)字節(jié),這樣就是12字節(jié)。
 
	intel:A.c 和B.c兩個(gè)c文件中使用了兩個(gè)相同名字的static變量,編譯的時(shí)候會(huì)不會(huì)有問(wèn)題?這兩個(gè)static變量會(huì)保存到哪里(棧還是堆或者其他的)?
 static的全局變量,表明這個(gè)變量?jī)H在本模塊中有意義,不會(huì)影響其他模塊。
 他們都放在數(shù)據(jù)區(qū),但是編譯器對(duì)他們的命名是不同的。
 如果要使變量在其他模塊也有意義的話(huà),需要使用extern關(guān)鍵字。
 
	struct s1{
 int i: 8;
 int j: 4;
 int a: 3;
 double b;
 };
 
	struct s2{
 int i: 8;
 int j: 4;
 double b;
 int a:3;
 };
 
	printf("sizeof(s1)= %d\n", sizeof(s1));printf("sizeof(s2)= %d\n", sizeof(s2));
 result: 16, 24
 第一個(gè)struct s1
 {
 int i: 8;
 int j: 4;
 int a: 3;
 double b;
 };
 理
論上是這樣的,首先是i在相對(duì)0的位置,占8位一個(gè)字節(jié),然后,j就在相對(duì)一個(gè)字節(jié)的位置,由于一個(gè)位置的字節(jié)數(shù)是4位的倍數(shù),因此不用對(duì)齊,就放在那里
了,然后是a,要在3位的倍數(shù)關(guān)系的位置上,因此要移一位,在15位的位置上放下,目前總共是18位,折算過(guò)來(lái)是2字節(jié)2位的樣子,由于double是8
字節(jié)的,因此要在相對(duì)0要是8個(gè)字節(jié)的位置上放下,因此從18位開(kāi)始到8個(gè)字節(jié)之間的位置被忽略,直接放在8字節(jié)的位置了,因此,總共是16字節(jié)。
 
	第二個(gè)最后會(huì)對(duì)照是不是結(jié)構(gòu)體內(nèi)最大數(shù)據(jù)的倍數(shù),不是的話(huà),會(huì)補(bǔ)成是最大數(shù)據(jù)的倍數(shù)
 
	上面是基本問(wèn)題,接下來(lái)是編程問(wèn)題:
 
	本人很弱,這幾個(gè)題也搞不定,特來(lái)求救:
 1)讀文件file1.txt的內(nèi)容(例如):
 12
 34
 56
 輸出到file2.txt:
 56
 34
 12
 (逆序)
 2)輸出和為一個(gè)給定整數(shù)的所有組合
 例如n=5
 5=1+4;5=2+3(相加的數(shù)不能重復(fù))
 則輸出
 1,4;2,3。
 望高手賜教??!
 
	第一題,注意可增長(zhǎng)數(shù)組的應(yīng)用.#i nclude
 #i nclude
 
	int main(void){
 int MAX = 10;
 int *a = (int *)malloc(MAX * sizeof(int));
 int *b;
 
 FILE *fp1;
 FILE *fp2;
 
	fp1 = fopen("a.txt","r");if(fp1 == NULL)
 {printf("error1");
 exit(-1);
 }
 
	    fp2 = fopen("b.txt","w");if(fp2 == NULL)
 {printf("error2");
 exit(-1);
 }
 
	int i = 0;int j = 0;
 
	while(fscanf(fp1,"%d",&a[i]) != EOF){
 i++;
 j++;
 if(i >= MAX)
 {
 MAX = 2 * MAX;
 b = (int*)realloc(a,MAX * sizeof(int));
 if(b == NULL)
 {
 printf("error3");
 exit(-1);
 }
 a = b;
 }
 }
 
	for(;--j >= 0;)fprintf(fp2,"%d\n",a[j]);
 
	fclose(fp1);fclose(fp2);
 
	return 0;}
 
	第二題.#i nclude
 
	int main(void){
 unsigned long int i,j,k;
 
	printf("please input the number\n");scanf("%d",&i);
 if( i % 2 == 0)
 j = i / 2;
 else
 j = i / 2 + 1;
 
	printf("The result is \n");for(k = 0; k < j; k++)
 printf("%d = %d + %d\n",i,k,i - k);
 return 0;
 }
 
	#i nclude void main()
 {
 unsigned long int a,i=1;
 scanf("%d",&a);
 if(a%2==0)
 {
 for(i=1;i
     printf("%d",a,a-i);
 }
 else
 for(i=1;i<=a/2;i++)
 printf(" %d, %d",i,a-i);
 }
 
	兄弟,這樣的題目若是做不出來(lái)實(shí)在是有些不應(yīng)該, 給你一個(gè)遞規(guī)反向輸出字符串的例子,可謂是反序的經(jīng)典例程.
 
	void inverse(char *p){
 if( *p = = '\0' )
 return;
 inverse( p+1 );
 printf( "%c", *p );
 }
 
	int main(int argc, char *argv[]){
 inverse("abc\0");
 
	    return 0;}
 
	借簽了樓上的“遞規(guī)反向輸出”#i nclude
 void test(FILE *fread, FILE *fwrite)
 {
 char buf[1024] = {0};
 if (!fgets(buf, sizeof(buf), fread))
 &nb
 
 
 
		北京德勝門(mén)中醫(yī)院www.
	 
		德勝門(mén)中醫(yī)院www.
	 
		杭州京都醫(yī)院www.
	 
		上海裝修公司www.
	 
		開(kāi)網(wǎng)店www.
	 
		奶茶加盟www.
	 
		漢堡加盟www.
	 |