1.嵌入式系統(tǒng)中經(jīng)常要用到無限循環(huán),如何用C編寫死循環(huán)
答:while(1){} 或者 for(;;) ?
2.程序的局部變量存在于哪里,全局變量存在于哪里,動態(tài)申請數(shù)據(jù)存在于哪里。
答:程序的局部變量存在于棧區(qū);全局變量存在于靜態(tài)區(qū);動態(tài)申請數(shù)據(jù)存在于堆區(qū)。 ?
3.關(guān)鍵字const有什么含義?
答:
1)只讀。 2)使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。 3)使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無意的代碼修改。 ?
4.請問以下代碼有什么問題:
?
int main() { char a; char *str = &a; strcpy(str,"hello"); printf(str); return 0; }
?
答:沒有為str分配內(nèi)存空間,將會發(fā)生異常,問題出在將一個字符串復(fù)制進(jìn)一個字符變量指針?biāo)傅刂贰km然可以正確輸出結(jié)果,但因為越界進(jìn)行內(nèi)在讀寫而導(dǎo)致程序崩潰。
5.已知一個數(shù)組table,用一個宏定義,求出數(shù)據(jù)的元素個數(shù)
答:#define NTBL (sizeof(table)/sizeof(table[0])) ?
6.寫一個"標(biāo)準(zhǔn)"宏MIN ,這個宏輸入兩個參數(shù)并返回較小的一個。
答:#define MIN(A,B) ((A) <= (B) ? (A) : (B))
考點:
1) 標(biāo)識#define在宏中應(yīng)用的基本知識。這是很重要的。因為在 嵌入(inline)操作符 變?yōu)闃?biāo)準(zhǔn)C的一部分之前,宏是方便產(chǎn)生嵌入代碼的唯一方法,對于嵌入式系統(tǒng)來說,為了能達(dá)到要求的性能,嵌入代碼經(jīng)常是必須的方法。
2) 三重條件操作符的知識。這個操作符存在C語言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)的代碼,了解這個用法是很重要的。
3) 懂得在宏中小心地把參數(shù)用括號括起來。 ?
7.do……while和while有什么區(qū)別?
答:前一個循環(huán)一遍再判斷,后一個判斷以后再循環(huán)。 ?
8.什么是預(yù)編譯,何時需要預(yù)編譯?
答:
1、總是使用不經(jīng)常改動的大型代碼體。
2、程序由多個模塊組成,所有模塊都使用一組標(biāo)準(zhǔn)的包含文件和相同的編譯選項。在這種情況下,可以將所有包含文件預(yù)編譯為一個預(yù)編譯頭。
預(yù)編譯指令指示了在程序正式編譯前就由編譯器進(jìn)行的操作,可以放在程序中的任何位置。 ?
9.一個32位的機(jī)器,該機(jī)器的指針是多少位?
答:指針是多少位只要看地址總線的位數(shù)就行了。80386以后的機(jī)子都是32的數(shù)據(jù)總線。所以指針的位數(shù)就是4個字節(jié)了。 ?
10.局部變量能否和全局變量重名?
答:能,局部會屏蔽全局。
局部變量可以與全局變量同名,在函數(shù)內(nèi)引用這個變量時,會用到同名的局部變量,而不會用到全局變量。
對于有些編譯器而言,在同一個函數(shù)內(nèi)可以定義多個同名的局部變量,比如在兩個循環(huán)體內(nèi)都定義一個同名的局部變量,而那個局部變量的作用域就在那個循環(huán)體內(nèi)。 ?
11.引用與指針有什么區(qū)別?
答:
1) 引用必須被初始化,指針不必。
2) 引用初始化以后不能被改變,指針可以改變所指的對象。
3) 不存在指向空值的引用,但是存在指向空值的指針。 ?
12.關(guān)鍵字static的作用是什么?
答:在C語言中,關(guān)鍵字static有三個明顯的作用:
1) 在函數(shù)體,一個被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。
2) 在模塊內(nèi)(但在函數(shù)體外),一個被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個本地的全局變量。
3) 在模塊內(nèi),一個被聲明為靜態(tài)的函數(shù)只可被這一模塊內(nèi)的其它函數(shù)調(diào)用。那就是,這個函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。 ?
13.static全局變量與普通的全局變量有什么區(qū)別?static函數(shù)與普通函數(shù)有什么區(qū)別?
答:全局變量(外部變量)的說明之前再冠以static 就構(gòu)成了靜態(tài)的全局變量。
全局變量本身就是靜態(tài)存儲方式,靜態(tài)全局變量當(dāng)然也是靜態(tài)存儲方式。這兩者在存儲方式上并無不同。
這兩者的區(qū)別雖在于非靜態(tài)全局變量的作用域是整個源程序, 當(dāng)一個源程序由多個源文件組成時,非靜態(tài)的全局變量在各個源文件中都是有效的。而靜態(tài)全局變量則限制了其作用域,即只在定義該變量的源文件內(nèi)有效, 在同一源程序的其它源文件中不能使用它。 由于靜態(tài)全局變量的作用域局限于一個源文件內(nèi),只能為該源文件內(nèi)的函數(shù)公用,因此可以避免在其它源文件中引起錯誤。 從以上分析可以看出,把局部變量改變?yōu)殪o態(tài)變量后是改變了它的存儲方式即改變了它的生存期。把全局變量改變?yōu)殪o態(tài)變量后是改變了它的作用域,限制了它的使用范圍。 static函數(shù)與普通函數(shù)作用域不同。僅在本文件。只在當(dāng)前源文件中使用的函數(shù)應(yīng)該說明為內(nèi)部函數(shù)(static),內(nèi)部函數(shù)應(yīng)該在當(dāng)前源文件中說明和定義。 對于可在當(dāng)前源文件以外使用的函數(shù),應(yīng)該在一個頭文件中說明,要使用這些函數(shù)的源文件要包含這個頭文件。 ?
14.進(jìn)程之間通信的途徑有哪些?
答:進(jìn)程間通信主要通過管道、消息、信號等途徑進(jìn)行。
1、無名管道( pipe ):管道是一種半雙工的通信方式,數(shù)據(jù)只能單向流動,而且只能在具有親緣關(guān)系的進(jìn)程間使用。進(jìn)程的親緣關(guān)系通常是指父子進(jìn)程關(guān)系。
2、高級管道(popen):將另一個程序當(dāng)做一個新的進(jìn)程在當(dāng)前程序進(jìn)程中啟動,則它算是當(dāng)前程序的子進(jìn)程,這種方式我們成為高級管道方式。
3、有名管道 (named pipe) :有名管道也是半雙工的通信方式,但是它允許無親緣關(guān)系進(jìn)程間的通信。
4、消息隊列( message queue ) :消息隊列是由消息的鏈表,存放在內(nèi)核中并由消息隊列標(biāo)識符標(biāo)識。消息隊列克服了信號傳遞信息少、管道只能承載無格式字節(jié)流以及緩沖區(qū)大小受限等缺點。
5、信號量( semophore ) :信號量是一個計數(shù)器,可以用來控制多個進(jìn)程對共享資源的訪問。它常作為一種鎖機(jī)制,防止某進(jìn)程正在訪問共享資源時,其他進(jìn)程也訪問該資源。因此,主要作為進(jìn)程間以及同一進(jìn)程內(nèi)不同線程之間的同步手段。
6、信號 ( sinal ) :信號是一種比較復(fù)雜的通信方式,用于通知接收進(jìn)程某個事件已經(jīng)發(fā)生。
7、共享內(nèi)存( shared memory ) :共享內(nèi)存就是映射一段能被其他進(jìn)程所訪問的內(nèi)存,這段共享內(nèi)存由一個進(jìn)程創(chuàng)建,但多個進(jìn)程都可以訪問。共享內(nèi)存是最快的 IPC 方式,它是針對其他進(jìn)程間通信方式運(yùn)行效率低而專門設(shè)計的。它往往與其他通信機(jī)制,如信號兩,配合使用,來實現(xiàn)進(jìn)程間的同步和通信。
8、套接字( socket ) :套接字也是一種進(jìn)程間通信機(jī)制,與其他通信機(jī)制不同的是,它可用于不同機(jī)器間的進(jìn)程通信。 ?
15.產(chǎn)生死鎖的原因是什么?
答:多個并發(fā)進(jìn)程因爭奪系統(tǒng)資源而產(chǎn)生相互等待的現(xiàn)象。即:一組進(jìn)程中的每個進(jìn)程都在等待某個事件發(fā)生,而只有這組進(jìn)程中的其他進(jìn)程才能觸發(fā)該事件,這就稱這組進(jìn)程發(fā)生了死鎖。
產(chǎn)生死鎖的本質(zhì)原因為:
1)系統(tǒng)資源有限。
2)進(jìn)程推進(jìn)順序不合理。 ?
16.死鎖的4個必要條件
答:
1、互斥:某種資源一次只允許一個進(jìn)程訪問,即該資源一旦分配給某個進(jìn)程,其他進(jìn)程就不能再訪問,直到該進(jìn)程訪問結(jié)束。
2、占有且等待:一個進(jìn)程本身占有資源(一種或多種),同時還有資源未得到滿足,正在等待其他進(jìn)程釋放該資源。
3、不可搶占:別人已經(jīng)占有了某項資源,你不能因為自己也需要該資源,就去把別人的資源搶過來。
4、循環(huán)等待:存在一個進(jìn)程鏈,使得每個進(jìn)程都占有下一個進(jìn)程所需的至少一種資源。
當(dāng)以上四個條件均滿足,必然會造成死鎖,發(fā)生死鎖的進(jìn)程無法進(jìn)行下去,它們所持有的資源也無法釋放。這樣會導(dǎo)致CPU的吞吐量下降。所以死鎖情況是會浪費(fèi)系統(tǒng)資源和影響計算機(jī)的使用性能的。那么,解決死鎖問題就是相當(dāng)有必要的了。 ?
17.死鎖的處理方式有哪些?
答:死鎖的處理方式主要從預(yù)防死鎖、避免死鎖、檢測與解除死鎖這四個方面來進(jìn)行處理。
預(yù)防死鎖:
1、資源一次性分配:(破壞請求和保持條件)
2、可剝奪資源:即當(dāng)某進(jìn)程新的資源未滿足時,釋放已占有的資源(破壞不可剝奪條件)
3、資源有序分配法:系統(tǒng)給每類資源賦予一個編號,每一個進(jìn)程按編號遞增的順序請求資源,釋放則相反(破壞環(huán)路等待條件)
避免死鎖:
預(yù)防死鎖的幾種策略,會嚴(yán)重地?fù)p害系統(tǒng)性能。因此在避免死鎖時,要施加較弱的限制,從而獲得 較滿意的系統(tǒng)性能。
由于在避免死鎖的策略中,允許進(jìn)程動態(tài)地申請資源。因而,系統(tǒng)在進(jìn)行資源分配之前預(yù)先計算資源分配的安全性。若此次分配不會導(dǎo)致系統(tǒng)進(jìn)入不安全狀態(tài),則將資源分配給進(jìn)程;否則,進(jìn)程等待。其中最具有代表性的避免死鎖算法是銀行家算法。
檢測死鎖:
首先為每個進(jìn)程和每個資源指定一個唯一的號碼;
然后建立資源分配表和進(jìn)程等待表
解除死鎖:
當(dāng)發(fā)現(xiàn)有進(jìn)程死鎖后,便應(yīng)立即把它從死鎖狀態(tài)中解脫出來,常采用的方法有:
1、剝奪資源:從其它進(jìn)程剝奪足夠數(shù)量的資源給死鎖進(jìn)程,以解除死鎖狀態(tài);
2、撤消進(jìn)程:可以直接撤消死鎖進(jìn)程或撤消代價最小的進(jìn)程,直至有足夠的資源可用,死鎖狀態(tài).消除為止;所謂代價是指優(yōu)先級、運(yùn)行代價、進(jìn)程的重要性和價值等。
18.進(jìn)程和線程有什么區(qū)別?
答:進(jìn)程是并發(fā)執(zhí)行的程序在執(zhí)行過程中分配和管理資源的基本單位。線程是進(jìn)程的一個執(zhí)行單元,是比進(jìn)程還要小的獨(dú)立運(yùn)行的基本單位。
一個程序至少有一個進(jìn)程,一個進(jìn)程至少有一個線程。兩者的區(qū)別主要有以下幾個方面:
1. 進(jìn)程是資源分配的最小單位。
2. 線程是程序執(zhí)行的最小單位,也是處理器調(diào)度的基本單位,但進(jìn)程不是。兩者均可并發(fā)執(zhí)行。
3. 進(jìn)程有自己的獨(dú)立地址空間,每啟動一個進(jìn)程,系統(tǒng)就會為它分配地址空間,建立數(shù)據(jù)表來維護(hù)代碼段、堆棧段和數(shù)據(jù)段,這種操作非常昂貴。而線程是共享進(jìn)程中的數(shù)據(jù),使用相同的地址空間,因此,CPU切換一個線程的花費(fèi)遠(yuǎn)比進(jìn)程小很多,同時創(chuàng)建一個線程的開銷也比進(jìn)程小很多。
4. 線程之間的通信更方便,同一進(jìn)程下的線程共享全局變量、靜態(tài)變量等數(shù)據(jù),而進(jìn)程之間的通信需要以通信的方式(IPC)進(jìn)行。不過如何處理好同步與互斥是編寫多線程程序的難點。但是多進(jìn)程程序更健壯,多線程程序只要有一個線程死掉,整個進(jìn)程也跟著死掉了,而一個進(jìn)程死掉并不會對另外一個進(jìn)程造成影響,因為進(jìn)程有自己獨(dú)立的地址空間。
5. 進(jìn)程切換時,消耗的資源大,效率低。所以涉及到頻繁的切換時,使用線程要好于進(jìn)程。同樣如果要求同時進(jìn)行并且又要共享某些變量的并發(fā)操作,只能用線程不能用進(jìn)程。
6. 執(zhí)行過程:每個獨(dú)立的進(jìn)程有一個程序運(yùn)行的入口、順序執(zhí)行序列和程序入口。但是線程不能獨(dú)立執(zhí)行,必須依存在應(yīng)用程序中,由應(yīng)用程序提供多個線程執(zhí)行控制。
優(yōu)缺點:
線程執(zhí)行開銷小,但是不利于資源的管理和保護(hù)。線程適合在SMP機(jī)器(雙CPU系統(tǒng))上運(yùn)行。
進(jìn)程執(zhí)行開銷大,但是能夠很好的進(jìn)行資源管理和保護(hù),可以跨機(jī)器遷移。
何時使用多進(jìn)程,何時使用多線程?
對資源的管理和保護(hù)要求高,不限制開銷和效率時,使用多進(jìn)程。
要求效率高,頻繁切換時,資源的保護(hù)管理要求不是很高時,使用多線程。 ?
19. 線程是否具有相同的堆棧?
答:真正的程序執(zhí)行都是線程來完成的,程序啟動的時候操作系統(tǒng)就幫你創(chuàng)建了一個主線程。
每個線程有自己的堆棧。 ?
20.TCP與UDP有啥區(qū)別?
答:TCP和UDP是OSI模型中的運(yùn)輸層中的協(xié)議。TCP提供可靠的通信傳輸,而UDP則常被用于廣播和細(xì)節(jié)控制交給應(yīng)用的通信傳輸,兩者主要的不同體現(xiàn)在一下幾個方面:
1、TCP面向連接(如打電話要先撥號建立連接);UDP是無連接的,即發(fā)送數(shù)據(jù)之前不需要建立連接
2、TCP提供可靠的服務(wù)。它通過校驗和,丟包時的重傳控制,序號標(biāo)識,滑動窗口、確認(rèn)應(yīng)答,次序亂掉的分包進(jìn)行順序控制實現(xiàn)可靠傳輸。即通過TCP連接傳送的數(shù)據(jù),無差錯,不丟失,不重復(fù),且按序到達(dá); UDP盡最大努力交付,即不保證可靠交付。
3、UDP具有較好的實時性,工作效率比TCP高,適用于對高速傳輸和實時性有較高要求的通信或廣播通信場景。
4、每一條TCP連接只能是點到點的; UDP支持一對一,一對多,多對一和多對多的交互通信方式。
5、TCP對系統(tǒng)資源要求較多,UDP對系統(tǒng)資源要求較少。
UDP有時比TCP更有優(yōu)勢:
UDP以其簡單、傳輸快的優(yōu)勢,在越來越多場景下取代了TCP, 如實時游戲。
(1)網(wǎng)速的提升給UDP的穩(wěn)定性提供可靠網(wǎng)絡(luò)保障,丟包率很低,如果使用應(yīng)用層重傳,能夠確保傳輸?shù)目煽啃浴?/p>
(2)TCP為了實現(xiàn)網(wǎng)絡(luò)通信的可靠性,使用了復(fù)雜的擁塞控制算法,建立了繁瑣的握手過程,由于TCP在內(nèi)置的系統(tǒng)協(xié)議棧中,極難對其進(jìn)行改進(jìn)。
采用TCP,一旦發(fā)生丟包,TCP會將后續(xù)的包緩存起來,等前面的包重傳并接收到后再繼續(xù)發(fā)送,延時會越來越大。
基于UDP對實時性要求較為嚴(yán)格的情況下,采用自定義重傳機(jī)制,能夠把丟包產(chǎn)生的延遲降到最低,盡量減少網(wǎng)絡(luò)問題造成的影響。
評論
查看更多