• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            A Za, A Za, Fighting...

            堅(jiān)信:勤能補(bǔ)拙

            給C瓜同學(xué)吧

            C瓜同學(xué)一直關(guān)注這個(gè)我這個(gè)小地方,下面是一些我面試中或者和同學(xué)討論的一些不錯(cuò)的面試題,備份一下,也希望對你有用。

            1:C++的多態(tài)是如何實(shí)現(xiàn)的?如果你用C如何來實(shí)現(xiàn)面向?qū)ο蟮亩鄳B(tài)?
            解:
            C++多態(tài)的實(shí)現(xiàn)主要依賴虛函數(shù)表,以及每個(gè)對象中指向虛函數(shù)表的指針
            至于如何用C來實(shí)現(xiàn)面向?qū)ο蟮亩鄳B(tài),我覺得比較靠譜的方法是函數(shù)指針,通過賦予函數(shù)指針不同的函數(shù)(地址)來調(diào)用不同的函數(shù),得到不同的結(jié)果

            2:判斷一個(gè)有向圖中是否有環(huán)。上篇文章里面寫的那個(gè)杯子倒水問題。給一個(gè)都是正整數(shù)的數(shù)組,和一個(gè)正整數(shù)sum,求是否存在和為sum的子數(shù)列。
            解:
            【判斷一個(gè)有向圖是否有環(huán)】

            【杯子倒水問題】
            把所有可能的操作列出來,寬度優(yōu)先搜索,從初始狀態(tài)到結(jié)束狀態(tài)

            【給一個(gè)都是正整數(shù)的數(shù)組,和一個(gè)正整數(shù)sum,求是否存在和為sum的子數(shù)列】

            聯(lián)想到的問題有:
            a. 給一個(gè)都是正整數(shù)的數(shù)組,是否存在兩個(gè)數(shù)的和為某個(gè)給定的sum? 三個(gè)數(shù)呢?
            針對兩個(gè)數(shù)的情況,可以先排序,然后一個(gè)指針front指向第一個(gè)元素(最小),一個(gè)指針tail指向最后一個(gè)元素(最大),如果*front + *tail < sum, ++front, 如果*front + *tail > sum, --tail;
            如果三個(gè)數(shù),或者N個(gè)數(shù),該如何做?

            動(dòng)態(tài)規(guī)劃,類似于01背包問題
            f[i][k]表示前i個(gè)元素中任意k個(gè)元素的和的集合,那么有:
                             f[i][k] = f[i-1][k] + (f[i-1][k-1] + array[i])
            or:
            f[i][v]表示前i個(gè)元素中是否存在和的v的子數(shù)列,那么有:
                             f[i][v] = 1, only if f[i-1][v]=1 or f[i-1][v-array[i]]=1

            3:兩個(gè)有大量id的集合A和B,數(shù)量上億級,如何求出兩個(gè)集合的交集,A中有的B中沒有的,和B中有的A中沒有的集合。
            涉及海量數(shù)據(jù)處理: 二分搜索、位圖Bitmap、哈希Hash、字典樹、分成若干小文件+多路歸并... 

            4:設(shè)計(jì)實(shí)現(xiàn)一個(gè)管理內(nèi)存的小模塊,接口為void* checkout(size_t size), void checkin(void* ptr)。

            5: 設(shè)計(jì)一個(gè)數(shù)據(jù)結(jié)構(gòu),存儲(chǔ)一副象棋子的擺放,盡量壓縮空間,使得方便通過傳輸?shù)搅硗庖慌_(tái)機(jī)子上然后恢復(fù)棋盤。

            6:數(shù)組的眾數(shù)問題,最長遞增子序列問題。找大量數(shù)據(jù)中前k個(gè)大的數(shù)。找大量數(shù)據(jù)中第k大的數(shù)。

            7:一個(gè)平面中有很多點(diǎn),用最快的算法找出相隔最近的兩個(gè)點(diǎn)。

            8:select/poll和epoll,基本互聯(lián)網(wǎng)公司都會(huì)提到這個(gè)東西。

            9:給敏感詞列表,和一大段文本,考慮一個(gè)敏感詞過濾的算法。

            10:海量數(shù)據(jù)問題,很多,一般方法就為分治、hash、位圖。

            很多沒有標(biāo)準(zhǔn)答案,面試過程中的探討很重要。找工作不難,找份好工作還是難的,基礎(chǔ)知識(shí)很重要,數(shù)據(jù)結(jié)構(gòu)和算法、操作系統(tǒng)、編程語言的掌握,數(shù)據(jù)庫和網(wǎng)絡(luò)。可以根據(jù)自己的喜好,偏向于某個(gè)方向。


            轉(zhuǎn)自: http://www.moorekang.com/2010/10/27/forc.html
            posted @ 2011-09-22 23:36 simplyzhao 閱讀(247) | 評論 (0)編輯 收藏

            基本解釋

              const是一個(gè)C語言的關(guān)鍵字,它限定一個(gè)變量不允許被改變。使用const在一定程度上可以提高程序的健壯性,另外,在觀看別人代碼的時(shí)候,清晰理解const所起的作用,對理解對方的程序也有一些幫助。

              雖然這聽起來很簡單,但實(shí)際上,const的使用也是c語言中一個(gè)比較微妙的地方,微妙在何處呢?請看下面幾個(gè)問題。

              問題:const變量 & 常量

              為什么我象下面的例子一樣用一個(gè)const變量來初始化數(shù)組,ANSI C的編譯器會(huì)報(bào)告一個(gè)錯(cuò)誤呢?

              const int n = 5;

              int a[n];

              答案與分析:

              1)、這個(gè)問題討論的是“常量”與“只讀變量”的區(qū)別。常量肯定是只讀的,例如5, “abc”,等,肯定是只讀的,因?yàn)槌绦蛑懈緵]有地方存放它的值,當(dāng)然也就不能夠去修改它。而“只讀變量”則是在內(nèi)存中開辟一個(gè)地方來存放它的值,只不過這個(gè)值由編譯器限定不允許被修改。C語言關(guān)鍵字const就是用來限定一個(gè)變量不允許被改變的修飾符(Qualifier)。上述代碼中變量n被修飾為只讀變量,可惜再怎么修飾也不是常量。而ANSI C規(guī)定數(shù)組定義時(shí)維度必須是“常量”,“只讀變量”也是不可以的。

              2)、注意:在ANSI C中,這種寫法是錯(cuò)誤的,因?yàn)閿?shù)組的大小應(yīng)該是個(gè)常量,而const int n,n只是一個(gè)變量(常量 != 不可變的變量,但在標(biāo)準(zhǔn)C++中,這樣定義的是一個(gè)常量,這種寫法是對的),實(shí)際上,根據(jù)編譯過程及內(nèi)存分配來看,這種用法本來就應(yīng)該是合理的,只是ANSI C對數(shù)組的規(guī)定限制了它。

              3)、那么,在ANSI C 語言中用什么來定義常量呢?答案是enum類型和#define宏,這兩個(gè)都可以用來定義常量。

              問題:const變量 & const 限定的內(nèi)容

              下面的代碼編譯器會(huì)報(bào)一個(gè)錯(cuò)誤,請問,哪一個(gè)語句是錯(cuò)誤的呢?

              typedef char * pStr;

              char string[4] = "abc";

              const char *p1 = string;

              const pStr p2 = string;

              p1++;

              p2++;

              答案與分析:

              問題出在p2++上。

              1)、const使用的基本形式: const char m;

              限定m不可變。

              2)、替換1式中的m, const char *pm;

              限定*pm不可變,當(dāng)然pm是可變的,因此問題中p1++是對的。

              3)、替換1式char, const newType m;

              限定m不可變,問題中的charptr就是一種新類型,因此問題中p2不可變,p2++是錯(cuò)誤的。

              問題:const變量 & 字符串常量

              請問下面的代碼有什么問題?

              char *p = "i'm hungry!";

              p[0]= 'I';

              答案與分析:

              上面的代碼可能會(huì)造成內(nèi)存的非法寫操作。分析如下, “i'm hungry”實(shí)質(zhì)上是字符串常量,而常量往往被編譯器放在只讀的內(nèi)存區(qū),不可寫。p初始指向這個(gè)只讀的內(nèi)存區(qū),而p[0] = 'I'則企圖去寫這個(gè)地方,編譯器當(dāng)然不會(huì)答應(yīng)。

              問題:const變量 & 字符串常量2

              請問char a[3] = "abc" 合法嗎?使用它有什么隱患?

              答案與分析:

              在標(biāo)準(zhǔn)C中這是合法的,但是它的生存環(huán)境非常狹小;它定義一個(gè)大小為3的數(shù)組,初始化為“abc”,,注意,它沒有通常的字符串終止符'\0',因此這個(gè)數(shù)組只是看起來像C語言中的字符串,實(shí)質(zhì)上卻不是,因此所有對字符串進(jìn)行處理的函數(shù),比如strcpy、printf等,都不能夠被使用在這個(gè)假字符串上。

              問題:const & 指針

              類型聲明中const用來修飾一個(gè)常量,有如下兩種寫法,那么,請問,下面分別用const限定不可變的內(nèi)容是什么?

              1)、const在前面

              const int nValue; //nValue是const

              const char *pContent; //*pContent是const, pContent可變

              const (char *) pContent;//pContent是const,*pContent可變

              char* const pContent; //pContent是const,*pContent可變

              const char* const pContent; //pContent和*pContent都是const

              2)、const在后面,與上面的聲明對等

              int const nValue; // nValue是const

              char const * pContent;// *pContent是const, pContent可變

              (char *) const pContent;//pContent是const,*pContent可變

              char* const pContent;// pContent是const,*pContent可變

              char const* const pContent;// pContent和*pContent都是const

              答案與分析:

              const和指針一起使用是C語言中一個(gè)很常見的困惑之處,在實(shí)際開發(fā)中,特別是在看別人代碼的時(shí)候,常常會(huì)因?yàn)檫@樣而不好判斷作者的意圖,下面講一下我的判斷原則:

              沿著*號劃一條線,const和誰在一邊,那么誰就是const,即const限定的元素就是它。你可以根據(jù)這個(gè)規(guī)則來看上面聲明的實(shí)際意義,相信定會(huì)一目了然。

              另外,需要注意:對于const (char *) ; 因?yàn)閏har *是一個(gè)整體,相當(dāng)于一個(gè)類型(如 char),因此,這是限定指針是const。

            posted @ 2011-09-21 15:00 simplyzhao 閱讀(175) | 評論 (0)編輯 收藏

            1. 用預(yù)處理指令#define 聲明一個(gè)常數(shù),用以表明1年中有多少秒(忽略閏年問題)

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

            2. 寫一個(gè)“標(biāo)準(zhǔn)”宏MIN,這個(gè)宏輸入兩個(gè)參數(shù)并返回較小的一個(gè)。

            #define MIN(A,B) ((A) <= (B) ?(A) : (B))
            這個(gè)測試是為下面的目的而設(shè)的:
            1). 標(biāo)識(shí)#define在宏中應(yīng)用的基本知識(shí)。這是很重要的,因?yàn)橹钡角度?inline)操作符變?yōu)闃?biāo)準(zhǔn)C的一部分,宏是方便產(chǎn)生嵌入代碼的唯一方法,
            對于嵌入式系統(tǒng)來說,為了能達(dá)到要求的性能,嵌入代碼經(jīng)常是必須的方法。
            2). 三重條件操作符的知識(shí)。這個(gè)操作符存在C語言中的原因是它使得編譯器能產(chǎn)生比if-then-else更優(yōu)化的代碼,了解這個(gè)用法是很重要的。
            3). 懂得在宏中小心地把參數(shù)用括號括起來
            4). 我也用這個(gè)問題開始討論宏的副作用,例如:當(dāng)你寫下面的代碼時(shí)會(huì)發(fā)生什么事?
            least = MIN(*p++, b);

            3. 預(yù)處理器標(biāo)識(shí)#error的目的是什么?

            如果你不知道答案,請看參考文獻(xiàn)1。這問題對區(qū)分一個(gè)正常的伙計(jì)和一個(gè)書呆子是很有用的。只有書呆子才會(huì)讀C語言課本的附錄去找出象這種
            問題的答案。當(dāng)然如果你不是在找一個(gè)書呆子,那么應(yīng)試者最好希望自己不要知道答案。

            死循環(huán)(Infinite loops)

            4. 嵌入式系統(tǒng)中經(jīng)常要用到無限循環(huán),你怎么樣用C編寫死循環(huán)呢?

            這個(gè)問題用幾個(gè)解決方案。我首選的方案是:
            while(1)
            {
            }
            一些程序員更喜歡如下方案:
            for(;;)
            {
            }
            這個(gè)實(shí)現(xiàn)方式讓我為難,因?yàn)檫@個(gè)語法沒有確切表達(dá)到底怎么回事。如果一個(gè)應(yīng)試者給出這個(gè)作為方案,我將用這個(gè)作為一個(gè)機(jī)會(huì)去探究他們這樣做的
            基本原理。如果他們的基本答案是:“我被教著這樣做,但從沒有想到過為什么。”這會(huì)給我留下一個(gè)壞印象。
            第三個(gè)方案是用 goto
            Loop:
            ...
            goto Loop;
            應(yīng)試者如給出上面的方案,這說明或者他是一個(gè)匯編語言程序員(這也許是好事)或者他是一個(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 integer)
            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)常聲稱這里有幾個(gè)問題是那種要翻一下書才能回答的問題,我同意這種說法。當(dāng)我寫這篇文章時(shí),為了確定語法的正確性,我的確查了一下書。
            但是當(dāng)我被面試的時(shí)候,我期望被問到這個(gè)問題(或者相近的問題)。因?yàn)樵诒幻嬖嚨倪@段時(shí)間里,我確定我知道這個(gè)問題的答案。應(yīng)試者如果不知道
            所有的答案(或至少大部分答案),那么也就沒有為這次面試做準(zhǔn)備,如果該面試者沒有為這次面試做準(zhǔn)備,那么他又能為什么出準(zhǔn)備呢?

            Static

            6. 關(guān)鍵字static的作用是什么?

            這個(gè)簡單的問題很少有人能回答完全。在C語言中,關(guān)鍵字static有三個(gè)明顯的作用:
            1). 在函數(shù)體,一個(gè)被聲明為靜態(tài)的變量在這一函數(shù)被調(diào)用過程中維持其值不變。
            2). 在模塊內(nèi)(但在函數(shù)體外),一個(gè)被聲明為靜態(tài)的變量可以被模塊內(nèi)所用函數(shù)訪問,但不能被模塊外其它函數(shù)訪問。它是一個(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是什么含意?
            我只要一聽到被面試者說:“const意味著常數(shù)”,我就知道我正在和一個(gè)業(yè)余者打交道。去年Dan Saks已經(jīng)在他的文章里完全概括了const的所有用法,因此ESP(譯者:Embedded Systems Programming)的每一位讀者應(yīng)該非常熟悉const能做什么和不能做什么.如果你從沒有讀到那篇文章,只要能說出const意味著“只讀”就可以了。盡管這個(gè)答案不是完全的答案,但我接受它作為一個(gè)正確的答案。(如果你想知道更詳細(xì)的答案,仔細(xì)讀一下Saks的文章吧。)如果應(yīng)試者能正確回答這個(gè)問題,我將問他一個(gè)附加的問題:下面的聲明都是什么意思?

            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ù)的常指針(也就是說,指針指向的整型數(shù)是可以修改的,但指針是不可修改的)。最后一個(gè)意味著a是一個(gè)指向常整型數(shù)的常指針(也就是說,指針指向的整型數(shù)是不可修改的,同時(shí)指針也是不可修改的)。如果應(yīng)試者能正確回答這些問題,那么他就給我留下了一個(gè)好印象。順帶提一句,也許你可能會(huì)問,即使不用關(guān)鍵字 const,也還是能很容易寫出功能正確的程序,那么我為什么還要如此看重關(guān)鍵字const呢?我也如下的幾下理由:
            1). 關(guān)鍵字const的作用是為給讀你代碼的人傳達(dá)非常有用的信息,實(shí)際上,聲明一個(gè)參數(shù)為常量是為了告訴了用戶這個(gè)參數(shù)的應(yīng)用目的。如果你曾花很多時(shí)間清理其它人留下的垃圾,你就會(huì)很快學(xué)會(huì)感謝這點(diǎn)多余的信息。(當(dāng)然,懂得用const的程序員很少會(huì)留下的垃圾讓別人來清理的。)
            2). 通過給優(yōu)化器一些附加的信息,使用關(guān)鍵字const也許能產(chǎn)生更緊湊的代碼。
            3). 合理地使用關(guān)鍵字const可以使編譯器很自然地保護(hù)那些不希望被改變的參數(shù),防止其被無意的代碼修改。簡而言之,這樣可以減少bug的出現(xiàn)。

            Volatile

            8. 關(guān)鍵字volatile有什么含意 并給出三個(gè)不同的例子。

            一個(gè)定義為volatile的變量是說這變量可能會(huì)被意想不到地改變,這樣,編譯器就不會(huì)去假設(shè)這個(gè)變量的值了。精確地說就是,優(yōu)化器在用到這個(gè)變量時(shí)必須每次都小心地重新讀取這個(gè)變量的值,而不是使用保存在寄存器里的備份。下面是volatile變量的幾個(gè)例子:
            1). 并行設(shè)備的硬件寄存器(如:狀態(tài)寄存器)
            2). 一個(gè)中斷服務(wù)子程序中會(huì)訪問到的非自動(dòng)變量(Non-automatic variables)
            3). 多線程應(yīng)用中被幾個(gè)任務(wù)共享的變量
            回答不出這個(gè)問題的人是不會(huì)被雇傭的。我認(rèn)為這是區(qū)分C程序員和嵌入式系統(tǒng)程序員的最基本的問題。嵌入式系統(tǒng)程序員經(jīng)常同硬件、中斷、RTOS等等打交道,所用這些都要求volatile變量。不懂得volatile內(nèi)容將會(huì)帶來災(zāi)難。
            假設(shè)被面試者正確地回答了這是問題(嗯,懷疑這否會(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). 是的。盡管這并不很常見。一個(gè)例子是當(dāng)一個(gè)中服務(wù)子程序修該一個(gè)指向一個(gè)buffer的指針時(shí)。
            3). 這段代碼的有個(gè)惡作劇。這段代碼的目的是用來返指針*ptr指向值的平方,但是,由于*ptr指向一個(gè)volatile型參數(shù),編譯器將產(chǎn)生類似下面的代碼:
            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)總是要用戶對變量或寄存器進(jìn)行位操作。給定一個(gè)整型變量a,寫兩段代碼,第一個(gè)設(shè)置a的bit 3,第二個(gè)清除a 的bit 3。在以上兩個(gè)操作中,要保持其它位不變。

            對這個(gè)問題有三種基本的反應(yīng)
            1). 不知道如何下手。該被面者從沒做過任何嵌入式系統(tǒng)的工作。
            2). 用bit fields。Bit fields是被扔到C語言死角的東西,它保證你的代碼在不同編譯器之間是不可移植的,同時(shí)也保證了的你的代碼是不可重用的。我最近不幸看到 Infineon為其較復(fù)雜的通信芯片寫的驅(qū)動(dòng)程序,它用到了bit fields因此完全對我無用,因?yàn)槲业木幾g器用其它的方式來實(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í)定義一些說明常數(shù),這也是可以接受的。我希望看到幾個(gè)要點(diǎn):說明常數(shù)、|=和&=~操作。

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

            10. 嵌入式系統(tǒng)經(jīng)常具有要求程序員去訪問某特定的內(nèi)存位置的特點(diǎn)。在某工程中,要求設(shè)置一絕對地址為0x67a9的整型變量的值為0xaa66。編譯器是一個(gè)純粹的ANSI編譯器。寫代碼去完成這一任務(wù)。

            這一問題測試你是否知道為了訪問一絕對地址把一個(gè)整型數(shù)強(qiáng)制轉(zhuǎn)換(typecast)為一指針是合法的。這一問題的實(shí)現(xiàn)方式隨著個(gè)人風(fēng)格不同而不同。典型的類似代碼如下:
            int *ptr;
            ptr = (int *)0x67a9;
            *ptr = 0xaa55;

            一個(gè)較晦澀的方法是:
            *(int * const)(0x67a9) = 0xaa55;

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

            中斷(Interrupts)

            11. 中斷是嵌入式系統(tǒng)中重要的組成部分,這導(dǎo)致了很多編譯開發(fā)商提供一種擴(kuò)展—讓標(biāo)準(zhǔn)C支持中斷。具代表事實(shí)是,產(chǎn)生了一個(gè)新的關(guān)鍵字 __interrupt。下面的代碼就使用了__interrupt關(guān)鍵字去定義了一個(gè)中斷服務(wù)子程序(ISR),請?jiān)u論一下這段代碼的。

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

            這個(gè)函數(shù)有太多的錯(cuò)誤了,以至讓人不知從何說起了:
            1). ISR 不能返回一個(gè)值。如果你不懂這個(gè),那么你不會(huì)被雇用的。
            2). ISR 不能傳遞參數(shù)。如果你沒有看到這一點(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)常有重入和性能上的問題。如果你丟掉了第三和第四點(diǎn),我不會(huì)太為難你的。不用說,如果你能得到后兩點(diǎn),那么你的被雇用前景越來越光明了。

            代碼例子(Code examples)

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

            void foo(void)
            {
            unsigned int a = 6;
            int b = -20;
            (a+b > 6) puts("> 6") : puts("<= 6");
            }


            這個(gè)問題測試你是否懂得C語言中的整數(shù)自動(dòng)轉(zhuǎn)換原則,我發(fā)現(xiàn)有些開發(fā)者懂得極少這些東西。不管如何,這無符號整型問題的答案是輸出是“>6”。原因是當(dāng)表達(dá)式中存在有符號類型和無符號類型時(shí)所有的操作數(shù)都自動(dòng)轉(zhuǎn)換為無符號類型。因此-20變成了一個(gè)非常大的正整數(shù),所以該表達(dá)式計(jì)算出的結(jié)果大于6。這一點(diǎn)對于應(yīng)當(dāng)頻繁用到無符號數(shù)據(jù)類型的嵌入式系統(tǒng)來說是豐常重要的。如果你答錯(cuò)了這個(gè)問題,你也就到了得不到這份工作的邊緣。

            13. 評價(jià)下面的代碼片斷:

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

            對于一個(gè)int型不是16位的處理器為說,上面的代碼是不正確的。應(yīng)編寫如下:

            unsigned int compzero = ~0;

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

            動(dòng)態(tài)內(nèi)存分配(Dynamic memory allocation)

            14. 盡管不像非嵌入式計(jì)算機(jī)那么常見,嵌入式系統(tǒng)還是有從堆(heap)中動(dòng)態(tài)分配內(nèi)存的過程的。那么嵌入式系統(tǒng)中,動(dòng)態(tài)分配內(nèi)存可能發(fā)生的問題是什么?

            這里,我期望應(yīng)試者能提到內(nèi)存碎片,碎片收集的問題,變量的持行時(shí)間等等。這個(gè)主題已經(jīng)在ESP雜志中被廣泛地討論過了(主要是 P.J. Plauger, 他的解釋遠(yuǎn)遠(yuǎn)超過我這里能提到的任何解釋),所有回過頭看一下這些雜志吧!讓應(yīng)試者進(jìn)入一種虛假的安全感覺后,我拿出這么一個(gè)小節(jié)目:下面的代碼片段的輸出是什么,為什么?

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

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

            Typedef

            15. Typedef 在C語言中頻繁用以聲明一個(gè)已經(jīng)存在的數(shù)據(jù)類型的同義字。也可以用預(yù)處理器做類似的事。例如,思考一下下面的例子:
            #define dPS struct s *
            typedef struct s * tPS;

            以上兩種情況的意圖都是要定義dPS 和 tPS 作為一個(gè)指向結(jié)構(gòu)s指針。哪種方法更好呢?(如果有的話)為什么?


            這是一個(gè)非常微妙的問題,任何人答對這個(gè)問題(正當(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è)指針。

            晦澀的語法

            16. C語言同意一些令人震驚的結(jié)構(gòu),下面的結(jié)構(gòu)是合法的嗎,如果是它做些什么?
            int a = 5, b = 7, c;
            c = a+++b;

            這個(gè)問題將做為這個(gè)測驗(yàn)的一個(gè)愉快的結(jié)尾。不管你相不相信,上面的例子是完全合乎語法的。問題是編譯器如何處理它?水平不高的編譯作者實(shí)際上會(huì)爭論這個(gè)問題,根據(jù)最處理原則,編譯器應(yīng)當(dāng)能處理盡可能所有合法的用法。因此,上面的代碼被處理成:
            c = a++ + b;
            因此, 這段代碼持行后a = 6, b = 7, c = 12。
            如果你知道答案,或猜出正確答案,做得好。如果你不知道答案,我也不把這個(gè)當(dāng)作問題。我發(fā)現(xiàn)這個(gè)問題的最大好處是:這是一個(gè)關(guān)于代碼編寫風(fēng)格,代碼的可讀性,代碼的可修改性的好的話題

            posted @ 2011-09-21 14:57 simplyzhao 閱讀(187) | 評論 (0)編輯 收藏
            大端模式與小端模式
            一、概念及詳解
              在各種體系的計(jì)算機(jī)中通常采用的字節(jié)存儲(chǔ)機(jī)制主要有兩種: big-endian和little-endian,即大端模式和小端模式。
              先回顧兩個(gè)關(guān)鍵詞,MSB和LSB:
              MSB:Most Significant Bit ------- 最高有效位
                    LSB:Least Significant Bit ------- 最低有效位
              大端模式(big-edian)
              big-endian:MSB存放在最低端的地址上。
              舉例,雙字節(jié)數(shù)0x1234以big-endian的方式存在起始地址0x00002000中:
                    | data |<-- address
                    | 0x12 |<-- 0x00002000
                    | 0x34 |<-- 0x00002001
              在Big-Endian中,對于bit序列中的序號編排方式如下(以雙字節(jié)數(shù)0x8B8A為例):
                    bit | 0 1 2 3 4 5 6 7 | 8 9 10 11 12 13 14 15
                    ------MSB----------------------------------LSB
                    val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
                    +--------------------------------------------+
                    = 0x8 B 8 A
              小端模式(little-endian)
              little-endian:LSB存放在最低端的地址上。
              舉例,雙字節(jié)數(shù)0x1234以little-endian的方式存在起始地址0x00002000中:
            | data |<-- address
                    | 0x34 |<-- 0x00002000
                    | 0x12 |<-- 0x00002001
              在Little-Endian中,對于bit序列中的序號編排和Big-Endian剛好相反,其方式如下(以雙字節(jié)數(shù)0x8B8A為例):
            bit | 15 14 13 12 11 10 9 8 | 7 6 5 4 3 2 1 0
                    ------MSB-----------------------------------LSB
                    val | 1 0 0 0 1 0 1 1 | 1 0 0 0 1 0 1 0 |
                    +---------------------------------------------+
                    = 0x8 B 8 A 
            二、數(shù)組在大端小端情況下的存儲(chǔ):
              以unsigned int value = 0x12345678為例,分別看看在兩種字節(jié)序下其存儲(chǔ)情況,我們可以用unsigned char buf[4]來表示value:
              Big-Endian: 低地址存放高位,如下:
                   高地址
                    ---------------
                    buf[3] (0x78) -- 低位
                    buf[2] (0x56)
                    buf[1] (0x34)
                    buf[0] (0x12) -- 高位
                    ---------------
                    低地址
            Little-Endian: 低地址存放低位,如下:
                    高地址
                    ---------------
                    buf[3] (0x12) -- 高位
                    buf[2] (0x34)
                    buf[1] (0x56)
                    buf[0] (0x78) -- 低位
                    --------------
                    低地址

              三、大端小端轉(zhuǎn)換方法:
              Big-Endian轉(zhuǎn)換成Little-Endian如下:
            #define BigtoLittle16(A)                 ((((uint16)(A) & 0xff00) >> 8) | \
                                                                      (((uint16)(A) & 0x00ff) << 8))
            #define BigtoLittle32(A)                 ((((uint32)(A) & 0xff000000) >> 24) | \
                                                                      (((uint32)(A) & 0x00ff0000) >> 8) | \
                                                                      (((uint32)(A) & 0x0000ff00) << 8) | \
                                                                      (((uint32)(A) & 0x000000ff) << 24))

              四、大端小端檢測方法:
              如何檢查處理器是big-endian還是little-endian?
              聯(lián)合體union的存放順序是所有成員都從低地址開始存放,利用該特性就可以輕松地獲得了CPU對內(nèi)存采用Little-endian還是Big-endian模式讀寫。
            int checkCPUendian()
            {
            union
            {
            unsigned int a;
            unsigned char b;
            }c;
            c.a = 1;
            return (c.b == 1);
            }
            /*return 1 : little-endian, return 0:big-endian*/ 

            網(wǎng)絡(luò)字節(jié)順序

            1、字節(jié)內(nèi)的比特位不受這種順序的影響
            比如一個(gè)字節(jié) 1000 0000 (或表示為十六進(jìn)制 80H)不管是什么順序其內(nèi)存中的表示法都是這樣。
            2、大于1個(gè)字節(jié)的數(shù)據(jù)類型才有字節(jié)順序問題
            比如 Byte A,這個(gè)變量只有一個(gè)字節(jié)的長度,所以根據(jù)上一條沒有字節(jié)順序問題。所以字節(jié)順序是“字節(jié)之間的相對順序”的意思。
            3、大于1個(gè)字節(jié)的數(shù)據(jù)類型的字節(jié)順序有兩種
            比如 short B,這是一個(gè)兩字節(jié)的數(shù)據(jù)類型,這時(shí)就有字節(jié)之間的相對順序問題了。
            網(wǎng)絡(luò)字節(jié)順序是“所見即所得”的順序。而Intel類型的CPU的字節(jié)順序與此相反。
            比如上面的 short B=0102H(十六進(jìn)制,每兩位表示一個(gè)字節(jié)的寬度)。所見到的是“0102”,按一般數(shù)學(xué)常識(shí),數(shù)軸從左到右的方向增加,即內(nèi)存地址從左到右增加的話,在內(nèi)存中這個(gè) short B的字節(jié)順序是:
            01 02
            這就是網(wǎng)絡(luò)字節(jié)順序。所見到的順序和在內(nèi)存中的順序是一致的!
            而相反的字節(jié)順序就不同了,其在內(nèi)存中的順序?yàn)椋?2 01
            假設(shè)通過抓包得到網(wǎng)絡(luò)數(shù)據(jù)的兩個(gè)字節(jié)流為:01 02
            如果這表示兩個(gè) Byte類型的變量,那么自然不需要考慮字節(jié)順序的問題。
            如果這表示一個(gè) short 變量,那么就需要考慮字節(jié)順序問題。根據(jù)網(wǎng)絡(luò)字節(jié)順序“所見即所得”的規(guī)則,這個(gè)變量的值就是:0102
            假設(shè)本地主機(jī)是Intel類型的,那么要表示這個(gè)變量,有點(diǎn)麻煩:
            定義變量 short X,
            字節(jié)流地址為:pt,按順序讀取內(nèi)存是為
            x=*((short*)pt);
            那么X的內(nèi)存順序當(dāng)然是 01 02
            按非“所見即所得”的規(guī)則,這個(gè)內(nèi)存順序和看到的一樣顯然是不對的,所以要把這兩個(gè)字節(jié)的位置調(diào)換。
            調(diào)換的方法可以自己定義,但用已經(jīng)有的API還是更為方便。

            網(wǎng)絡(luò)字節(jié)順序與主機(jī)字節(jié)順序
            NBO與HBO 網(wǎng)絡(luò)字節(jié)順序NBO(Network Byte Order):按從高到低的順序存儲(chǔ),在網(wǎng)絡(luò)上使用統(tǒng)一的網(wǎng)絡(luò)字節(jié)順序,可以避免兼容性問題。主機(jī)字節(jié)順序(HBO,Host Byte Order):不同的機(jī)器HBO不相同,與CPU設(shè)計(jì)有關(guān)計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,所以對于在內(nèi)部是以低位字節(jié)優(yōu)先方式存儲(chǔ)數(shù)據(jù)的機(jī)器,在Internet上傳輸數(shù)據(jù)時(shí)就需要進(jìn)行轉(zhuǎn)換。 

            htonl()
            簡述:
                將主機(jī)的無符號長整形數(shù)轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
                #include <winsock.h>
                u_long PASCAL FAR htonl( u_long hostlong);
                hostlong:主機(jī)字節(jié)順序表達(dá)的32位數(shù)。
            注釋:
                本函數(shù)將一個(gè)32位數(shù)從主機(jī)字節(jié)順序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)順序。
            返回值:
                htonl()返回一個(gè)網(wǎng)絡(luò)字節(jié)順序的值。

            inet_ntoa()
            簡述:
            將網(wǎng)絡(luò)地址轉(zhuǎn)換成“.”點(diǎn)隔的字符串格式。
            #include <winsock.h>
            char FAR* PASCAL FAR inet_ntoa( struct in_addr in);
            in:一個(gè)表示Internet主機(jī)地址的結(jié)構(gòu)。
            注釋:
            本函數(shù)將一個(gè)用in參數(shù)所表示的Internet地址結(jié)構(gòu)轉(zhuǎn)換成以“.” 間隔的諸如“a.b.c.d”的字符串形式。請注意inet_ntoa()返回的字符串存放在WINDOWS套接口實(shí)現(xiàn)所分配的內(nèi)存中。應(yīng)用程序不應(yīng)假設(shè)該內(nèi)存是如何分配的。在同一個(gè)線程的下一個(gè)WINDOWS套接口調(diào)用前,數(shù)據(jù)將保證是有效。
            返回值:
            若無錯(cuò)誤發(fā)生,inet_ntoa()返回一個(gè)字符指針。否則的話,返回NULL。其中的數(shù)據(jù)應(yīng)在下一個(gè)WINDOWS套接口調(diào)用前復(fù)制出來。

            網(wǎng)絡(luò)中傳輸?shù)臄?shù)據(jù)有的和本地字節(jié)存儲(chǔ)順序一致,而有的則截然不同,為了數(shù)據(jù)的一致性,就要把本地的數(shù)據(jù)轉(zhuǎn)換成網(wǎng)絡(luò)上使用的格式,然后發(fā)送出去,接收的時(shí)候也是一樣的,經(jīng)過轉(zhuǎn)換然后才去使用這些數(shù)據(jù),基本的庫函數(shù)中提供了這樣的可以進(jìn)行字節(jié)轉(zhuǎn)換的函數(shù),如和htons( ) htonl( ) ntohs( ) ntohl( ),這里n表示network,h表示host,htons( ) htonl( )用于本地字節(jié)向網(wǎng)絡(luò)字節(jié)轉(zhuǎn)換的場合,s表示short,即對2字節(jié)操作,l表示long即對4字節(jié)操作。同樣ntohs( )ntohl( )用于網(wǎng)絡(luò)字節(jié)向本地格式轉(zhuǎn)換的場合。
            posted @ 2011-09-21 13:03 simplyzhao 閱讀(233) | 評論 (0)編輯 收藏

            原文在http://hi.baidu.com/deep_pro/blog/item/cf964b0ade9f4d1594ca6b1b.html

            這些詞之間的區(qū)別難倒了很多人,還有什么同步阻塞, 同步非阻塞, 異步阻塞, 異步非阻塞,亂七八糟的。
            很多文章也想講明白這個(gè)問題。著名且引起熱議的有

            http://www.ibm.com/developerworks/cn/linux/l-async/

            http://www.shnenglu.com/converse/archive/2009/05/13/82879.html

            可是看了之后還是有點(diǎn)將信將疑,跑到圖書館翻了UNP 第一卷,不愧是圣經(jīng)級別的著作,似有所悟。
            UNP所述:
            POSIX定義中,同步IO操作:IO操作將導(dǎo)致請求進(jìn)程阻塞,直到IO操作完成。
            異步IO操作:IO操作不導(dǎo)致請求進(jìn)程阻塞

            UNP中總結(jié)的IO模型有5種之多
            阻塞IO,非阻塞IO,IO復(fù)用,信號驅(qū)動(dòng)IO,異步IO,前四種都屬于同步IO。

            阻塞IO不必說了
            非阻塞IO ,IO請求時(shí)加上O_NONBLOCK一類的標(biāo)志位,立刻返回,IO沒有就緒會(huì)返回錯(cuò)誤,需要請求進(jìn)程主動(dòng)輪詢不斷發(fā)IO請求直到返回正確
            IO復(fù)用同非阻塞IO本質(zhì)一樣,不過利用了新的select系統(tǒng)調(diào)用,由內(nèi)核來負(fù)責(zé)本來是請求進(jìn)程該做的輪詢操作。看似比非阻塞IO還多了一個(gè)系統(tǒng)調(diào)用開銷,不過因?yàn)榭梢灾С侄嗦稩O,才算提高了效率
            信號驅(qū)動(dòng)IO,調(diào)用sigaltion系統(tǒng)調(diào)用,當(dāng)內(nèi)核中IO數(shù)據(jù)就緒時(shí)以SIGIO信號通知請求進(jìn)程,請求進(jìn)程再把數(shù)據(jù)從內(nèi)核讀入到用戶空間,這一步是阻塞的。
            異步IO,如定義所說,不會(huì)因?yàn)镮O操作阻塞,IO操作全部完成才通知請求進(jìn)程。

            這樣以來,同步和阻塞,異步和非阻塞就不會(huì)被混淆了,它們不是同一個(gè)方面上的概念,不能比較區(qū)別

            同步和異步是只跟IO操作過程中進(jìn)程的狀態(tài)變化有關(guān)
            阻塞和非阻塞就是進(jìn)程的兩種狀態(tài)。

            posted @ 2011-09-09 17:03 simplyzhao 閱讀(256) | 評論 (0)編輯 收藏
                 摘要: C++ 虛函數(shù)表解析 陳皓http://blog.csdn.net/haoel  前言 C++中的虛函數(shù)的作用主要是實(shí)現(xiàn)了多態(tài)的機(jī)制。關(guān)于多態(tài),簡而言之就是用父類型別的指針指向其子類的實(shí)例,然后通過父類的指針調(diào)用實(shí)際子類的成員函數(shù)。這種技術(shù)可以讓父類的指針有“多種形態(tài)”,這是一種泛型技術(shù)。所謂泛型技術(shù),說白了就是試圖使用不變...  閱讀全文
            posted @ 2011-09-07 19:22 simplyzhao 閱讀(236) | 評論 (0)編輯 收藏
                 摘要: epoll方法實(shí)現(xiàn)non-blocking socketPosted on 2011/06/17 by Min© Min的技術(shù)分享 – 54min.com (RSS訂閱) | 原文鏈接:http://54min.com/post/using-epoll-method-create-non-blocking-socket.htm...  閱讀全文
            posted @ 2011-09-05 20:00 simplyzhao 閱讀(4675) | 評論 (0)編輯 收藏
                 摘要: HTTP protocolPosted on 2011/05/02 by Min© Min的技術(shù)分享 – 54min.com (RSS訂閱) | 原文鏈接:http://54min.com/post/the-http-protocol.htmlHTTP protocolHTTP是應(yīng)用層協(xié)議(傳輸層采用TCP因此是面向連接的),...  閱讀全文
            posted @ 2011-09-04 22:19 simplyzhao 閱讀(404) | 評論 (0)編輯 收藏
            問題:
            寫一個(gè)函數(shù) unsigned RevBit(unsigned val);

            unsigned x = RevBit(0xf0ec9999);
            x應(yīng)該為 0x9999370f。

            0xf0ec9999 == 11110000111011001001100110011001(二進(jìn)制)

            0x9999370f == 10011001100110010011011100001111(二進(jìn)制)


            思路:相鄰兩位互調(diào)位置(即一位換一位),再相鄰的兩位換兩位,在相鄰的四位與四位互調(diào)位置,再八位與八位互調(diào)位置,最后前十六位和后十六位互換位置,完成32位整數(shù)逆轉(zhuǎn)。思路與歸并排序相似。

            代碼:
            #include <stdio.h>;
             
            unsigned RevBit(unsigned x)
            {
            x
            =(x&0x55555555)<<1|(x>>1)&0x55555555;
            x
            =(x&0x33333333)<<2|(x>>2)&0x33333333;
            x
            =(x&0x0f0f0f0f)<<4|(x>>4)&0x0f0f0f0f;
            x
            =(x&0x00ff00ff)<<8|(x>>8)&0x00ff00ff;
            x
            =x<<16|x>>16;
            return x;
            }
             
            int main()
            {
            unsigned x 
            = RevBit(0xf0ec9999);
            printf(
            "%x\n",x);
            return 0;
            }

            更多解法: http://graphics.stanford.edu/~seander/bithacks.html#BitReverseObvious
            posted @ 2011-09-04 16:03 simplyzhao 閱讀(346) | 評論 (0)編輯 收藏

            題目

            1. 給你n個(gè)數(shù),其中有且僅有一個(gè)數(shù)出現(xiàn)了奇數(shù)次,其余的數(shù)都出現(xiàn)了偶數(shù)次。用線性時(shí)間常數(shù)空間找出出現(xiàn)了奇數(shù)次的那一個(gè)數(shù)。
            2. 給你n個(gè)數(shù),其中有且僅有兩個(gè)數(shù)出現(xiàn)了奇數(shù)次,其余的數(shù)都出現(xiàn)了偶數(shù)次。用線性時(shí)間常數(shù)空間找出出現(xiàn)了奇數(shù)次的那兩個(gè)數(shù)。

            答案

            1. 從頭到尾異或一遍,最后得到的那個(gè)數(shù)就是出現(xiàn)了奇數(shù)次的數(shù)。這是因?yàn)楫惢蛴幸粋€(gè)神奇的性質(zhì):兩次異或同一個(gè)數(shù),結(jié)果不變。再考慮到異或運(yùn)算滿足交換律,先異或和后異或都是一樣的,因此這個(gè)算法顯然正確。

            2. 從頭到尾異或一遍,你就得到了需要求的兩個(gè)數(shù)異或后的值。這兩個(gè)數(shù)顯然不相等,異或出來的結(jié)果不為0。我們可以據(jù)此找出兩個(gè)數(shù)的二進(jìn)制表達(dá)中不同的一位,然后把所有這n個(gè)數(shù)分成兩類,在那一位上是0的分成一類,在那一位上是1的分到另一類。對每一類分別使用前一個(gè)問題的算法。

            posted @ 2011-09-04 15:37 simplyzhao 閱讀(224) | 評論 (0)編輯 收藏
            僅列出標(biāo)題
            共21頁: 1 2 3 4 5 6 7 8 9 Last 

            導(dǎo)航

            <2011年10月>
            2526272829301
            2345678
            9101112131415
            16171819202122
            23242526272829
            303112345

            統(tǒng)計(jì)

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評論

            閱讀排行榜

            評論排行榜

            精品久久久久久无码中文字幕 | 亚洲AⅤ优女AV综合久久久| 99久久无码一区人妻| 久久se精品一区二区| 麻豆国内精品久久久久久| 99久久国产精品免费一区二区| 无码人妻精品一区二区三区久久| 久久99国产精品久久99| 午夜福利91久久福利| 俺来也俺去啦久久综合网| 色婷婷噜噜久久国产精品12p| 久久精品www人人爽人人| 久久精品一区二区影院| 久久综合久久自在自线精品自| 99久久国产综合精品网成人影院| 囯产精品久久久久久久久蜜桃 | 久久婷婷色综合一区二区| 久久精品国产男包| 国产精品99久久久久久www| 麻豆亚洲AV永久无码精品久久| 伊人久久综合成人网| 久久精品国产亚洲7777| 久久综合九色综合网站| 色8激情欧美成人久久综合电| 色婷婷噜噜久久国产精品12p| 久久AAAA片一区二区| 日韩精品无码久久久久久| 2019久久久高清456| 久久无码精品一区二区三区| 精品国产热久久久福利| 岛国搬运www久久| 免费国产99久久久香蕉| 精品久久久久久无码专区| 久久久www免费人成精品| 综合久久精品色| 亚洲精品乱码久久久久久蜜桃| 亚洲一级Av无码毛片久久精品| 无码精品久久一区二区三区| 国产精品成人无码久久久久久| 国产精品成人99久久久久 | 九九热久久免费视频|