當前位置:首頁 » 編程語言 » 智博通電子c語言面試題
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

智博通電子c語言面試題

發布時間: 2022-05-13 08:00:20

① 電子專業 面試題

我也是電子專業的,主要是考察數電模電和單片機,如果你是搞通訊設備,信號與系統和數字信號處理也要准備的,以下是我搜集的一些試題和部分答案,希望對你有幫助!
模擬電路

1、 基爾霍夫定理的內容是什麼?(仕蘭微電子)
基爾霍夫電流定律是一個電荷守恆定律,即在一個電路中流入一個節點的電荷與流出同一個節點的電荷相等.
基爾霍夫電壓定律是一個能量守恆定律,即在一個迴路中迴路電壓之和為零.
2、平板電容公式(C=εS/4πkd)。(未知)
3、最基本的如三極體曲線特性。(未知)
4、描述反饋電路的概念,列舉他們的應用。(仕蘭微電子)
5、負反饋種類(電壓並聯反饋,電流串聯反饋,電壓串聯反饋和電流並聯反饋);負反饋的優點(降低放大器的增益靈敏度,改變輸入電阻和輸出電阻,改善放大器的線性和非線性失真,有效地擴展放大器的通頻帶,自動調節作用)(未知)
6、放大電路的頻率補償的目的是什麼,有哪些方法?(仕蘭微電子)
7、頻率響應,如:怎麼才算是穩定的,如何改變頻響曲線的幾個方法。(未知)
8、給出一個查分運放,如何相位補償,並畫補償後的波特圖。(凹凸)
9、基本放大電路種類(電壓放大器,電流放大器,互導放大器和互阻放大器),優缺 點
,特別是廣泛採用差分結構的原因。(未知)
10、給出一差分電路,告訴其輸出電壓Y+和Y-,求共模分量和差模分量。(未知)
11、畫差放的兩個輸入管。(凹凸)
12、畫出由運放構成加法、減法、微分、積分運算的電路原理圖。並畫出一個晶體管級的
運放電路。(仕蘭微電子)
13、用運算放大器組成一個10倍的放大器。(未知)
14、給出一個簡單電路,讓你分析輸出電壓的特性(就是個積分電路),並求輸出端某點
的 rise/fall時間。(Infineon筆試試題)
15、電阻R和電容C串聯,輸入電壓為R和C之間的電壓,輸出電壓分別為C上電壓和R上電壓,要求制這兩種電路輸入電壓的頻譜,判斷這兩種電路何為高通濾波器,何為低通濾波器。當RC<< period - setup ? hold
16、時鍾周期為T,觸發器D1的建立時間最大為T1max,最小為T1min。組合邏輯電路最大延遲為T2max,最小為T2min。問,觸發器D2的建立時間T3和保持時間應滿足什麼條件.(華為)
17、給出某個一般時序電路的圖,有Tsetup,Tdelay,Tck->q,還有 clock的delay,寫出決定最大時鍾的因素,同時給出表達式。(威盛VIA 2003.11.06 上海筆試試題)
18、說說靜態、動態時序模擬的優缺點。(威盛VIA
2003.11.06 上海筆試試題)
19、一個四級的Mux,其中第二級信號為關鍵信號 如何改善timing。(威盛VIA2003.11.06 上海筆試試題)
20、給出一個門級的圖,又給了各個門的傳輸延時,問關鍵路徑是什麼,還問給出輸入,使得輸出依賴於關鍵路徑。(未知)
21、邏輯方面數字電路的卡諾圖化簡,時序(同步非同步差異),觸發器有幾種(區別,優點),全加器等等。(未知)
22、卡諾圖寫出邏輯表達使。(威盛VIA 2003.11.06 上海筆試試題)

____________________________________________________________
信號與系統
1、的話音頻率一般為300~3400HZ,若對其采樣且使信號不失真,其最小的采樣頻率應為多大?若採用8KHZ的采樣頻率,並採用8bit的PCM編碼,則存儲一秒鍾的信號數據量有多大?(仕蘭微面試題目)
2、什麼耐奎斯特定律,怎麼由模擬信號轉為數字信號。(華為面試題)
3、如果模擬信號的帶寬為 5khz,要用8K的采樣率,怎麼辦?lucent) 兩路?
4、信號與系統:在時域與頻域關系。(華為面試題)
5、給出時域信號,求其直流分量。(未知)
6、給出一時域信號,要求(1)寫出頻率分量,(2)寫出其傅立葉變換級數;(3)當波形經過低通濾波器濾掉高次諧波而只保留一次諧波時,畫出濾波後的輸出波形。(未知)
7、sketch 連續正弦信號和連續矩形波(都有圖)的傅立葉變換 。(Infineon筆試試題)
8、拉氏變換和傅立葉變換的表達式及聯系。(新太硬體面題)
____________________________________________________________
DSP、嵌入式、軟體等
1、請用方框圖描述一個你熟悉的實用數字信號處理系統,並做簡要的分析;如果沒有,也可以自己設計一個簡單的數字信號處理系統,並描述其功能及用途。(仕蘭微面試題目)
2、數字濾波器的分類和結構特點。(仕蘭微面試題目)
3、IIR,FIR濾波器的異同。(新太硬體面題)
4、拉氏變換與Z變換公式等類似東西,隨便翻翻書把如.h(n)=-a*h(n-1)+b*δ(n) a.求h(n)的z變換;b.問該系統是否為穩定系統;c.寫出FIR數字濾波器的差分方程;(未知)
5、DSP和通用處理器在結構上有什麼不同,請簡要畫出你熟悉的一種DSP結構圖。(信威dsp軟體面試題)
6、說說定點DSP和浮點DSP的定義(或者說出他們的區別)(信威dsp軟體面試題)
7、說說你對循環定址和位反序定址的理解.(信威dsp軟體面試題)
8、請寫出【-8,7】的二進制補碼,和二進制偏置碼。用Q15表示出0.5和-0.5.(信威dsp軟體面試題)
9、DSP的結構(哈佛結構);(未知)
10、嵌入式處理器類型(如ARM),操作系統種類(Vxworks,ucos,winCE,linux),操作系統
方面偏CS方向了,在CS篇裡面講了;(未知)
11、有一個LDO晶元將用於對手機供電,需要你對他進行評估,你將如何設計你的測試項目?
12、某程序在一個嵌入式系統(200M CPU,50M SDRAM)中已經最優化了,換到零一個系統
(300M CPU,50M SDRAM)中是否還需要優化? (Intel)
13、請簡要描述HUFFMAN編碼的基本原理及其基本的實現方法。(仕蘭微面試題目)
14、說出OSI七層網路協議中的四層(任意四層)。(仕蘭微面試題目)
15、A) (仕蘭微面試題目)
#i nclude
void testf(int*p)
{
*p+=1;
}
main()
{
int *n,m[2];
n=m;
m[0]=1;
m[1]=8;
testf(n);
printf("Data v alue is %d ",*n);
}
------------------------------
B)
#i nclude
void testf(int**p)
{
*p+=1;
}
main()
{int *n,m[2];
n=m;
m[0]=1;
m[1]=8;
testf(&n);
printf(Data v alue is %d",*n);
}
下面的結果是程序A還是程序B的?
Data v alue is 8
那麼另一段程序的結果是什麼?
16、那種排序方法最快? (華為面試題)
17、寫出兩個排序演算法,問哪個好?(威盛)
18、編一個簡單的求n!的程序 。(Infineon筆試試題)
19、用一種編程語言寫n!的演算法。(威盛VIA 2003.11.06 上海筆試試題)
20、用c語言寫一個遞歸演算法求N!;(華為面試題)
描述反饋電路的概念,列舉他們的應用。
反饋,就是在電子系統中,把輸出迴路中的電量輸入到輸入迴路中去。
反饋的類型有:電壓串聯負反饋、電流串聯負反饋、電壓並聯負反饋、電流並聯負反饋。
負反饋的優點:降低放大器的增益靈敏度,改變輸入電阻和輸出電阻,改善放大器的線性和非線性失真,有效地擴展放大器的通頻帶,自動調節作用。
電壓負反饋的特點:電路的輸出電壓趨向於維持恆定。
電流負反饋的特點:電路的輸出電流趨向於維持恆定。
3、有源濾波器和無源濾波器的區別
無源濾波器:這種電路主要有無源元件R、L和C組成
有源濾波器:集成運放和R、C組成,具有不用電感、體積小、重量輕等優點。
集成運放的開環電壓增益和輸入阻抗均很高,輸出電阻小,構成有源濾波電路後還具有一定的電壓放大和緩沖作用。但集成運放帶寬有限,所以目前的有源濾波電路的工作頻率難以做得很高。
數字電路
1、同步電路和非同步電路的區別是什麼?
同步電路:存儲電路中所有觸發器的時鍾輸入端都接同一個時鍾脈沖源,因而所有觸發器的狀態的變化都與所加的時鍾脈沖信號同步。
非同步電路:電路沒有統一的時鍾,有些觸發器的時鍾輸入端與時鍾脈沖源相連,這有這些觸發器的狀態變化與時鍾脈沖同步,而其他的觸發器的狀態變化不與時鍾脈沖同步。
2、什麼是"線與"邏輯,要實現它,在硬體特性上有什麼具體要求?
將兩個門電路的輸出端並聯以實現與邏輯的功能成為線與。
在硬體上,要用OC門來實現,同時在輸出埠加一個上拉電阻。
由於不用OC門可能使灌電流過大,而燒壞邏輯門。
3、解釋setup和hold time violation,畫圖說明,並說明解決辦法。(威盛VIA2003.11.06上海筆試試題)
Setup/hold time是測試晶元對輸入信號和時鍾信號之間的時間要求。建立時間是指觸發器的時鍾信號上升沿到來以前,數據穩定不變的時間。輸入信號應提前時鍾上升沿(如上升沿有效)T時間到達晶元,這個T就是建立時間-Setup time.如不滿足setup time,這個數據就不能被這一時鍾打入觸發器,只有在下一個時鍾上升沿,數據才能被打入觸發器。
保持時間是指觸發器的時鍾信號上升沿到來以後,數據穩定不變的時間。如果hold time不夠,數據同樣不能被打入觸發器。
建立時間(Setup Time)和保持時間(Hold time)。建立時間是指在時鍾邊沿前,數據信號需要保持不變的時間。保持時間是指時鍾跳變邊沿後數據信號需要保持不變的時間。如果數據信號在時鍾沿觸發前後持續的時間均超過建立和保持時間,那麼超過量就分別被稱為建立時間裕量和保持時間裕量。
4、什麼是競爭與冒險現象?怎樣判斷?如何消除?(漢王筆試)
在組合邏輯中,由於門的輸入信號通路中經過了不同的延時,導致到達該門的時間不一致叫競爭。
產生毛刺叫冒險。如果布爾式中有相反的信號則可能產生競爭和冒險現象。
解決方法:一是添加布爾式的消去項,二是在晶元外部加電容。
5、名詞:SRAM、SSRAM、SDRAM
SRAM:靜態RAM
DRAM:動態RAM
SSRAM:Synchronous Static Random Access Memory同步靜態隨機訪問存儲器。它的一種類型的SRAM。SSRAM的所有訪問都在時鍾的上升/下降沿啟動。地址、數據輸入和其它控制信號均於時鍾信號相關。這一點與非同步SRAM不同,非同步SRAM的訪問獨立於時鍾,數據輸入和輸出都由地址的變化控制。
SDRAM:Synchronous DRAM同步動態隨機存儲器
6、FPGA和ASIC的概念,他們的區別。(未知)
答案:FPGA是可編程ASIC。
ASIC:專用集成電路,它是面向專門用途的電路,專門為一個用戶設計和製造的。根據一個用戶的特定要求,能以低研製成本,短、交貨周期供貨的全定製,半定製集成電路。與 門陣列等其它ASIC(Application Specific IC)相比,它們又具有設計開發周期短、設計製造成本低、開發工具先進、標准產品無需測試、質量穩定以及可實時在線檢驗等優點。
7、什麼叫做OTP片、掩膜片,兩者的區別何在?
OTP means one time program,一次性編程
MTP means multi time program,多次性編程
OTP(One Time Program)是MCU的一種存儲器類型
MCU按其存儲器類型可分為MASK(掩模)ROM、OTP(一次性可編程)ROM、FLASHROM等類型。
MASKROM的MCU價格便宜,但程序在出廠時已經固化,適合程序固定不變的應用場合;
FALSHROM的MCU程序可以反復擦寫,靈活性很強,但價格較高,適合對價格不敏感的應用場合或做開發用途;
OTP ROM的MCU價格介於前兩者之間,同時又擁有一次性可編程能力,適合既要求一定靈活性,又要求低成本的應用場合,尤其是功能不斷翻新、需要迅速量產的電子產品。
8、單片機上電後沒有運轉,首先要檢查什麼?
首先應該確認電源電壓是否正常。用電壓表測量接地引腳跟電源引腳之間的電壓,看是否是電源電壓,例如常用的5V。
接下來就是檢查復位引腳電壓是否正常。分別測量按下復位按鈕和放開復位按鈕的電壓值,看是否正確。
然後再檢查晶振是否起振了,一般用示波器來看晶振引腳的波形,注意應該使用示波器探頭的「X10」檔。另一個辦法是測量復位狀態下的IO口電平,按住復位鍵不放,然後測量IO口(沒接外部上拉的P0口除外)的電壓,看是否是高電平,如果不是高電平,則多半是因為晶振沒有起振。
另外還要注意的地方是,如果使用片內ROM的話(大部分情況下如此,現在已經很少有用外部擴ROM的了),一定要將EA引腳拉高,否則會出現程序亂跑的情況。有時用模擬器可以,而燒入片子不行,往往是因為EA引腳沒拉高的緣故(當然,晶振沒起振也是原因只一)。經過上面幾點的檢查,一般即可排除故障了。如果系統不穩定的話,有時是因為電源濾波不好導致的。在單片機的電源引腳跟地引腳之間接上一個0.1uF的電容會有所改善。如果電源沒有濾波電容的話,則需要再接一個更大濾波電容,例如220uF的。遇到系統不穩定時,就可以並上電容試試(越靠近晶元越好)。

1、二極體的導通時的壓降。
答:0.7V。
2、三極體的工作條件。
答:B極(基極)在有一定的電壓時,發射極電壓應該在0.3V以上。
3、TTL電平的電壓值。
答:5V上下浮動10%,即4.5V―5.5V。
4、電路分析主要講的是什麼,或者是圍繞著什麼講的?
答:兩個定理,即基爾霍夫電壓定理,基爾霍夫電流定理。
5、數字信號處理的實質。
答:數字演算法或數學演算法。通過數學或數字演算法實現頻譜搬移,從而達到濾
波的效果。
6、單片機匯流排。
答:數據匯流排、控制匯流排、地址匯流排。P0口為I/O口,即可以是數據線,也可以是地址線,倘若都要使用時,要用鎖存器將二者分開,做地址線時,充當地址線的低8位,高8位由P2口充當。
7、晶振的接法或分類。
答:內接晶振和外接晶振。晶振與口線的距離越近越好。否則,會對其他部分造成高頻干擾。
8、鍵盤與控制器(或者是單片機)連接時時如何工作的。
答:通過控制器(或者是單片機)對鍵盤掃描,即:通過鍵盤與控制器相連導線上的電平值來判斷按下的鍵盤,從而判斷相應的鍵盤值,通過中斷,調用相應的中斷服務子程序。一般是通過鍵盤的行掃描和列掃描判斷鍵盤。
9、通信的三種解調方式。
答:調頻、調相、調幅。
10、語音信號的范圍和傳輸比特。
答:語音信號的頻率為300―3400赫茲,取上限頻率。一般取4000赫茲,有抽樣定理可知最低抽樣頻率為8000赫茲,中國採用PCM編碼調制,即位8段,因此傳輸比特為64K。(順便提一點,中國採用的是A律,與歐洲是一樣的,即13折線,日本、美國用的是u律,15折線)
11、2M帶寬。
答:語音傳輸是64K,中國用的是30/32線路系統,64K*32=2048k,即為我們所說的2M.
12、無線傳輸為什麼都是用的高頻。
答:從客觀上來說,使用的頻段是已經訂好的,常用的是80M―120M。從專業角度上來分析,是因為在高頻段上能提供較為理想的信道,達到信息良好的傳輸和帶寬的資源有效利用,而且這樣所提供的信道帶寬也比較寬。
13、CDMA技術。
答:CDMA技術是碼分多址技術,是無線通訊產品和服務的新時代率先開發的、用於提供十分清晰的語音效果的數字技術。通過利用數字編碼"擴譜"無線電頻率技術,CDMA能夠提供比其他無線技術更好的、成本更低的語音效果、保密性、系統容量和靈活性,以及更加完善的服務。
14、CDMA的工作。
答:CDMA利用擴譜技術將語音分解成數字化的小片斷,然後進行編碼,以區別每個電話。因而,大量的用戶能夠共享相同的頻譜,從而大大提高系統的性能。也就是說,CDMA使無線服務提供商將更多的數字化信號擠壓到一定的無線網路片斷中去。
15、常用的信道復用技術。
答:頻分多路復用(FDM),時分多路復用(TDM),頻分多址 (FDMA),時分多址(TDMA),碼分多址(CDMA)。
16、單片機對系統的濾波。
答:單片機對系統只能實現數字濾波,即通過一種數字演算法對系統進行濾波。常用的有中值濾波,平滑濾波,程序濾波等

② c語言常見面試題

C語言面試常見問題
預處理器(Preprocessor)

1 . 用預處理指令#define 聲明一個常數,用以表明1年中有多少秒(忽略閏年問題)
#define SECONDS_PER_YEAR (60 * 60 * 24 * 365)UL
我在這想看到幾件事情:
1) #define 語法的基本知識(例如:不能以分號結束,括弧的使用,等等)
2)懂得預處理器將為你計算常數表達式的值,因此,直接寫出你是如何計算一年中有多少秒而不是計算出實際的值,是更清晰而沒有代價的。
3) 意識到這個表達式將使一個16位機的整型數溢出-因此要用到長整型符號L,告訴編譯器這個常數是的長整型數。
4) 如果你在你的表達式中用到UL(表示無符號長整型),那麼你有了一個好的起點。記住,第一印象很重要。

2 . 寫一個"標准"宏MIN ,這個宏輸入兩個參數並返回較小的一個。
#define MIN(A,B) ((A) <= (B) ? (A) : (B))
這個測試是為下面的目的而設的:
1) 標識#define在宏中應用的基本知識。這是很重要的。因為在 嵌入(inline)操作符 變為標准C的一部分之前,宏是方便產生嵌入代碼的唯一方法,對於嵌入式系統來說,為了能達到要求的性能,嵌入代碼經常是必須的方法。
2)三重條件操作符的知識。這個操作符存在C語言中的原因是它使得編譯器能產生比if-then-else更優化的代碼,了解這個用法是很重要的。
3) 懂得在宏中小心地把參數用括弧括起來
4) 我也用這個問題開始討論宏的副作用,例如:當你寫下面的代碼時會發生什麼事?
least = MIN(*p++, b);

3. 預處理器標識#error的目的是什麼?
如果你不知道答案,請看參考文獻1。這問題對區分一個正常的伙計和一個書獃子是很有用的。只有書獃子才會讀C語言課本的附錄去找出象這種問題的答案。當然如果你不是在找一個書獃子,那麼應試者最好希望自己不要知道答案。

死循環(Infinite loops)

4. 嵌入式系統中經常要用到無限循環,你怎麼樣用C編寫死循環呢?
這個問題用幾個解決方案。我首選的方案是:

while(1)
{

}

一些程序員更喜歡如下方案:

for(;;)
{

}

這個實現方式讓我為難,因為這個語法沒有確切表達到底怎麼回事。如果一個應試者給出這個作為方案,我將用這個作為一個機會去探究他們這樣做的基本原理。如果他們的基本答案是:"我被教著這樣做,但從沒有想到過為什麼。"這會給我留下一個壞印象。

第三個方案是用 goto
Loop:
...
goto Loop;
應試者如給出上面的方案,這說明或者他是一個匯編語言程序員(這也許是好事)或者他是一個想進入新領域的BASIC/FORTRAN程序員。

數據聲明(Data declarations)

5. 用變數a給出下面的定義
a) 一個整型數(An integer)
b)一個指向整型數的指針( A pointer to an integer)
c)一個指向指針的的指針,它指向的指針是指向一個整型數( A pointer to a pointer to an intege)r
d)一個有10個整型數的數組( An array of 10 integers)
e) 一個有10個指針的數組,該指針是指向一個整型數的。(An array of 10 pointers to integers)
f) 一個指向有10個整型數數組的指針( A pointer to an array of 10 integers)
g) 一個指向函數的指針,該函數有一個整型參數並返回一個整型數(A pointer to a function that takes an integer as an argument and returns an integer)
h) 一個有10個指針的數組,該指針指向一個函數,該函數有一個整型參數並返回一個整型數( 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

人們經常聲稱這里有幾個問題是那種要翻一下書才能回答的問題,我同意這種說法。當我寫這篇文章時,為了確定語法的正確性,我的確查了一下書。但是當我被面試的時候,我期望被問到這個問題(或者相近的問題)。因為在被面試的這段時間里,我確定我知道這個問題的答案。應試者如果不知道所有的答案(或至少大部分答案),那麼也就沒有為這次面試做准備,如果該面試者沒有為這次面試做准備,那麼他又能為什麼出准備呢?

Static

6. 關鍵字static的作用是什麼?
這個簡單的問題很少有人能回答完全。在C語言中,關鍵字static有三個明顯的作用:
1)在函數體,一個被聲明為靜態的變數在這一函數被調用過程中維持其值不變。
2) 在模塊內(但在函數體外),一個被聲明為靜態的變數可以被模塊內所用函數訪問,但不能被模塊外其它函數訪問。它是一個本地的全局變數。
3) 在模塊內,一個被聲明為靜態的函數只可被這一模塊內的其它函數調用。那就是,這個函數被限制在聲明它的模塊的本地范圍內使用。

大多數應試者能正確回答第一部分,一部分能正確回答第二部分,同是很少的人能懂得第三部分。這是一個應試者的嚴重的缺點,因為他顯然不懂得本地化數據和代碼范圍的好處和重要性。

Const

7.關鍵字const有什麼含意?
我只要一聽到被面試者說:"const意味著常數",我就知道我正在和一個業余者打交道。去年Dan Saks已經在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應該非常熟悉const能做什麼和不能做什麼.如果你從沒有讀到那篇文章,只要能說出const意味著"只讀"就可以了。盡管這個答案不是完全的答案,但我接受它作為一個正確的答案。(如果你想知道更詳細的答案,仔細讀一下Saks的文章吧。)
如果應試者能正確回答這個問題,我將問他一個附加的問題:
下面的聲明都是什麼意思?

const int a;
int const a;
const int *a;
int * const a;
int const * a const;

/******/
前兩個的作用是一樣,a是一個常整型數。第三個意味著a是一個指向常整型數的指針(也就是,整型數是不可修改的,但指針可以)。第四個意思a是一個指向整型數的常指針(也就是說,指針指向的整型數是可以修改的,但指針是不可修改的)。最後一個意味著a是一個指向常整型數的常指針(也就是說,指針指向的整型數是不可修改的,同時指針也是不可修改的)。如果應試者能正確回答這些問題,那麼他就給我留下了一個好印象。順帶提一句,也許你可能會問,即使不用關鍵字 const,也還是能很容易寫出功能正確的程序,那麼我為什麼還要如此看重關鍵字const呢?我也如下的幾下理由:
1) 關鍵字const的作用是為給讀你代碼的人傳達非常有用的信息,實際上,聲明一個參數為常量是為了告訴了用戶這個參數的應用目的。如果你曾花很多時間清理其它人留下的垃圾,你就會很快學會感謝這點多餘的信息。(當然,懂得用const的程序員很少會留下的垃圾讓別人來清理的。)
2) 通過給優化器一些附加的信息,使用關鍵字const也許能產生更緊湊的代碼。
3) 合理地使用關鍵字const可以使編譯器很自然地保護那些不希望被改變的參數,防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現。

Volatile

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

回答不出這個問題的人是不會被僱傭的。我認為這是區分C程序員和嵌入式系統程序員的最基本的問題。搞嵌入式的傢伙們經常同硬體、中斷、RTOS等等打交道,所有這些都要求用到volatile變數。不懂得volatile的內容將會帶來災難。
假設被面試者正確地回答了這是問題(嗯,懷疑是否會是這樣),我將稍微深究一下,看一下這傢伙是不是直正懂得volatile完全的重要性。
1)一個參數既可以是const還可以是volatile嗎?解釋為什麼。
2); 一個指針可以是volatile 嗎?解釋為什麼。
3); 下面的函數有什麼錯誤:

int square(volatile int *ptr)
{
return *ptr * *ptr;
}

下面是答案:
1)是的。一個例子是只讀的狀態寄存器。它是volatile因為它可能被意想不到地改變。它是const因為程序不應該試圖去修改它。
2); 是的。盡管這並不很常見。一個例子是當一個中服務子程序修該一個指向一個buffer的指針時。
3) 這段代碼有點變態。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由於*ptr指向一個volatile型參數,編譯器將產生類似下面的代碼:

int square(volatile int *ptr)
{
int a,b;
a = *ptr;
b = *ptr;
return a * b;
}

由於*ptr的值可能被意想不到地該變,因此a和b可能是不同的。結果,這段代碼可能返不是你所期望的平方值!正確的代碼如下:

long square(volatile int *ptr)
{
int a;
a = *ptr;
return a * a;
}

位操作(Bit manipulation)

9. 嵌入式系統總是要用戶對變數或寄存器進行位操作。給定一個整型變數a,寫兩段代碼,第一個設置a的bit 3,第二個清除a 的bit 3。在以上兩個操作中,要保持其它位不變。
對這個問題有三種基本的反應
1)不知道如何下手。該被面者從沒做過任何嵌入式系統的工作。
2) 用bit fields。Bit fields是被扔到C語言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時也保證了的你的代碼是不可重用的。我最近不幸看到 Infineon為其較復雜的通信晶元寫的驅動程序,它用到了bit fields因此完全對我無用,因為我的編譯器用其它的方式來實現bit fields的。從道德講:永遠不要讓一個非嵌入式的傢伙粘實際硬體的邊。
3) 用 #defines 和 bit masks 操作。這是一個有極高可移植性的方法,是應該被用到的方法。最佳的解決方案如下:

#define BIT3 (0x1 << 3)
static int a;

void set_bit3(void)
{
a |= BIT3;
}
void clear_bit3(void)
{
a &= ~BIT3;
}

一些人喜歡為設置和清除值而定義一個掩碼同時定義一些說明常數,這也是可以接受的。我希望看到幾個要點:說明常數、|=和&=~操作。

訪問固定的內存位置(Accessing fixed memory locations)

10. 嵌入式系統經常具有要求程序員去訪問某特定的內存位置的特點。在某工程中,要求設置一絕對地址為0x67a9的整型變數的值為0xaa66。編譯器是一個純粹的ANSI編譯器。寫代碼去完成這一任務。
這一問題測試你是否知道為了訪問一絕對地址把一個整型數強制轉換(typecast)為一指針是合法的。這一問題的實現方式隨著個人風格不同而不同。典型的類似代碼如下:
int *ptr;
ptr = (int *)0x67a9;
*ptr = 0xaa55;

A more obscure approach is:
一個較晦澀的方法是:

*(int * const)(0x67a9) = 0xaa55;

即使你的品味更接近第二種方案,但我建議你在面試時使用第一種方案。

中斷(Interrupts)

11. 中斷是嵌入式系統中重要的組成部分,這導致了很多編譯開發商提供一種擴展—讓標准C支持中斷。具代表事實是,產生了一個新的關鍵字 __interrupt。下面的代碼就使用了__interrupt關鍵字去定義了一個中斷服務子程序(ISR),請評論一下這段代碼的。

__interrupt double compute_area (double radius)
{
double area = PI * radius * radius;
printf("\nArea = %f", area);
return area;
}

這個函數有太多的錯誤了,以至讓人不知從何說起了:
1)ISR 不能返回一個值。如果你不懂這個,那麼你不會被僱用的。
2) ISR 不能傳遞參數。如果你沒有看到這一點,你被僱用的機會等同第一項。
3) 在許多的處理器/編譯器中,浮點一般都是不可重入的。有些處理器/編譯器需要讓額處的寄存器入棧,有些處理器/編譯器就是不允許在ISR中做浮點運算。此外,ISR應該是短而有效率的,在ISR中做浮點運算是不明智的。
4) 與第三點一脈相承,printf()經常有重入和性能上的問題。如果你丟掉了第三和第四點,我不會太為難你的。不用說,如果你能得到後兩點,那麼你的被僱用前景越來越光明了。

代碼例子(Code examples)

12 . 下面的代碼輸出是什麼,為什麼?

void foo(void)
{
unsigned int a = 6;
int b = -20;
(a+b > 6) ? puts("> 6") : puts("<= 6");
}
這個問題測試你是否懂得C語言中的整數自動轉換原則,我發現有些開發者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是 ">6"。原因是當表達式中存在有符號類型和無符號類型時所有的操作數都自動轉換為無符號類型。因此-20變成了一個非常大的正整數,所以該表達式計算出的結果大於6。這一點對於應當頻繁用到無符號數據類型的嵌入式系統來說是豐常重要的。如果你答錯了這個問題,你也就到了得不到這份工作的邊緣。

13. 評價下面的代碼片斷:

unsigned int zero = 0;
unsigned int compzero = 0xFFFF;
/*1's complement of zero */

對於一個int型不是16位的處理器為說,上面的代碼是不正確的。應編寫如下:

unsigned int compzero = ~0;

這一問題真正能揭露出應試者是否懂得處理器字長的重要性。在我的經驗里,好的嵌入式程序員非常准確地明白硬體的細節和它的局限,然而PC機程序往往把硬體作為一個無法避免的煩惱。
到了這個階段,應試者或者完全垂頭喪氣了或者信心滿滿志在必得。如果顯然應試者不是很好,那麼這個測試就在這里結束了。但如果顯然應試者做得不錯,那麼我就扔出下面的追加問題,這些問題是比較難的,我想僅僅非常優秀的應試者能做得不錯。提出這些問題,我希望更多看到應試者應付問題的方法,而不是答案。不管如何,你就當是這個娛樂吧...

動態內存分配(Dynamic memory allocation)

14. 盡管不像非嵌入式計算機那麼常見,嵌入式系統還是有從堆(heap)中動態分配內存的過程的。那麼嵌入式系統中,動態分配內存可能發生的問題是什麼?
這里,我期望應試者能提到內存碎片,碎片收集的問題,變數的持行時間等等。這個主題已經在ESP雜志中被廣泛地討論過了(主要是 P.J. Plauger, 他的解釋遠遠超過我這里能提到的任何解釋),所有回過頭看一下這些雜志吧!讓應試者進入一種虛假的安全感覺後,我拿出這么一個小節目:
下面的代碼片段的輸出是什麼,為什麼?

char *ptr;
if ((ptr = (char *)malloc(0)) == NULL)
puts("Got a null pointer");
else
puts("Got a valid pointer");

這是一個有趣的問題。最近在我的一個同事不經意把0值傳給了函數malloc,得到了一個合法的指針之後,我才想到這個問題。這就是上面的代碼,該代碼的輸出是"Got a valid pointer"。我用這個來開始討論這樣的一問題,看看被面試者是否想到庫常式這樣做是正確。得到正確的答案固然重要,但解決問題的方法和你做決定的基本原理更重要些。

Typedef

15 Typedef 在C語言中頻繁用以聲明一個已經存在的數據類型的同義字。也可以用預處理器做類似的事。例如,思考一下下面的例子:

#define dPS struct s *
typedef struct s * tPS;

以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個指向結構s指針。哪種方法更好呢?(如果有的話)為什麼?
這是一個非常微妙的問題,任何人答對這個問題(正當的原因)是應當被恭喜的。答案是:typedef更好。思考下面的例子:

dPS p1,p2;
tPS p3,p4;

第一個擴展為

struct s * p1, p2;
.
上面的代碼定義p1為一個指向結構的指,p2為一個實際的結構,這也許不是你想要的。第二個例子正確地定義了p3 和p4 兩個指針。

晦澀的語法

16 . C語言同意一些令人震驚的結構,下面的結構是合法的嗎,如果是它做些什麼?

int a = 5, b = 7, c;
c = a+++b;

這個問題將做為這個測驗的一個愉快的結尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實際上會爭論這個問題,根據最處理原則,編譯器應當能處理盡可能所有合法的用法。因此,上面的代碼被處理成:

c = a++ + b;

因此, 這段代碼持行後a = 6, b = 7, c = 12。
如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個當作問題。我發現這個問題的最大好處是這是一個關於代碼編寫風格,代碼的可讀性,代碼的可修改性的好的話題。