【正文】
題開(kāi)始討論宏的副作用,例如:當(dāng)你寫下面的代碼時(shí)會(huì)發(fā)生什么事? least = MIN(*p++, b)。這問(wèn)題對(duì)區(qū)分一個(gè)正常的伙計(jì)和一個(gè)書呆子是很有用的。當(dāng)然如果你不是在找一個(gè)書呆子,那么應(yīng)試者最好希望自己不要知道答案。我首選的方案是: while(1) { } 一些程序員更喜歡如下方案: for(。如果一個(gè)應(yīng)試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機(jī)會(huì)去探究他們這樣做的 基本原理。這會(huì)給我留下一個(gè)壞印象。 應(yīng)試者如給出上面的方案,這說(shuō)明或者他是一個(gè)匯編語(yǔ)言程序員(這也許是好事)或者他是一個(gè)想進(jìn)入新領(lǐng)域的BASIC/FORTRAN程序員。 // An integer b) int *a。 // A pointer to a pointer to an integer d) int a[10]。 // An array of 10 pointers to integers f) int (*a)[10]。 // A pointer to a function a that takes an integer argument and returns an integer h) int (*a[10])(int)。當(dāng)我寫這篇文章時(shí),為了確定語(yǔ)法的正確性,我的確查了一下書。因?yàn)樵诒幻嬖嚨倪@段時(shí)間里,我確定我知道這個(gè)問(wèn)題的答案。在C語(yǔ)言中,關(guān)鍵字static有三個(gè)明顯的作用: 1). 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過(guò)程中維持其值不變。它是一個(gè)本地的全局變量。那就是,這個(gè)函數(shù)被限制在聲明它的模塊的本地范圍內(nèi)使用。這是一個(gè)應(yīng)試者的嚴(yán)重的缺點(diǎn),因?yàn)樗@然不懂得本地化數(shù)據(jù)和代碼范圍的好處和重要性。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming),只要能說(shuō)出const意味著只讀就可以了。(如果你想知道更詳細(xì)的答案,仔細(xì)讀一下Saks的文章吧。 int const a。 int * const a。前兩個(gè)的作用是一樣,a是一個(gè)常整型數(shù)。第四個(gè)意思a是一個(gè)指向整型數(shù)的常指針(也就是說(shuō),指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。如果應(yīng)試者能正確回答這些問(wèn)題,那么他就給我留下了一個(gè)好印象。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。) 2). 通過(guò)給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。簡(jiǎn)而言之,這樣可以減少bug的出現(xiàn)。一個(gè)定義為volatile的變量是說(shuō)這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。下面是volatile變量的幾個(gè)例子: 1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器) 2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問(wèn)到的非自動(dòng)變量(Nonautomatic variables) 3). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量 回答不出這個(gè)問(wèn)題的人是不會(huì)被雇傭的。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。 假設(shè)被面試者正確地回答了這是問(wèn)題(嗯,懷疑這否會(huì)是這樣),我將稍微深究一下,看一下這家伙是不是直正懂得volatile完全的重要性。 2). 一個(gè)指針可以是volatile 嗎?解釋為什么。 } 下面是答案: 1). 是的。它是volatile因?yàn)樗赡鼙灰庀氩坏降馗淖儭?2). 是的。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。這段代碼的目的是用來(lái)返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼: int square(volatile int *ptr) { int a,b。 b = *ptr。 } 由于*ptr的值可能被意想不到地該變,因此a和b可能是不同的。 a =