不得不看的C語言中的基礎問題(一)

2021-07-24 04:22:31 字數 2384 閱讀 7688

預處理器(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)

下面是答案:

1)是的。乙個例子是唯讀的狀態暫存器。它是volatile因為它可能被意想不到地改變。它是const因為程式不應該試圖去修改它。

2); 是的。儘管這並不很常見。乙個例子是當乙個中服務子程式修該乙個指向乙個buffer的指標時。

3) 這段**有點**。這段**的目的是用來返指標*ptr指向值的平方,但是,由於*ptr指向乙個volatile型引數,編譯器將產生類似下面的**:

int square(volatile int *ptr)

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

long square(volatile int *ptr)

位操作(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)

void clear_bit3(void)

訪問固定的記憶體位置(accessing fixed memory locations)

10. 嵌入式系統經常具有要求程式設計師去訪問某特定的記憶體位置的特點。在某工程中,要求設定一絕對位址為0x67a9的整型變數的值為0xaa66。編譯器是乙個純粹的ansi編譯器。寫**去完成這一任務。

這一問題測試你是否知道為了訪問一絕對位址把乙個整型數強制轉換(typecast)為一指標是合法的。這一問題的實現方式隨著個人風格不同而不同。典型的類似**如下:

int *ptr;

ptr = (int *)0x67a9;

*ptr = 0xaa55;

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

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

this指向 不得不看的this指向問題

分析this的指向共有四種型別 1 函式被呼叫時 即執行時 才會確定該函式內this的指向。因為在函式中this與arguments是兩個特殊的變數,在函式被呼叫時才會取得它們,而且搜尋這兩個變數時只會在活動物件範圍裡面去搜。2 要確定函式中this的指向,必須先找到該函式被呼叫的位置。認準第一種 ...

IT人士不得不看的成長手冊

作為it技術人員,相信沒有乙個人願意永遠在底層編寫程式或做簡單的系統維護。經過一段時間的技術和經驗的積累,很多人都嚮往更高層的職位,但如何能成為乙個專業的it管理人才,並不是每乙個人都清晰 明了。如果你真想成為一名成功 成熟的it專家,你需要不斷地擴充套件你的技能與知識 有些知識領域可能對你很陌生,...

不得不看的B樹索引

一 先導 練習 31 18 73 9 27 37 99 上面資料經過一系列插入後 變成了有序的結構,且符合二叉樹的特性 但是如果是同一組數 9 18 27 31 37 73 99 公升序後再排序 這種情況出現了嚴重的傾斜,這是比較極端的情況 二叉樹變成線性結構了,查詢效率明顯降低,沒有發揮出二叉樹的...