• <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>

            xyjzsh

            c++編程習(xí)慣(1)

            1.盡量使用一個(gè)構(gòu)造函數(shù)。
            原因:如果使用多個(gè)構(gòu)造函數(shù),可能導(dǎo)致在有很多個(gè)實(shí)例變量的時(shí)候沒(méi)有在所有的構(gòu)造函數(shù)中初始化,從而造成錯(cuò)誤!
            可以用默認(rèn)值的方法來(lái)達(dá)到提供默認(rèn)構(gòu)造函數(shù)。
            2.在考慮跨平臺(tái)時(shí)要盡量不使用int,unsigned系列的類型,因?yàn)椴煌脚_(tái)對(duì)它們所占的字節(jié)數(shù)不一定相同。
            3.技巧:使用
            do
            {
            }while(0);
            這樣就可以在合適的時(shí)候break。然后在while后面做最后的處理。
            class A
            {
            .....
            };

            4.對(duì)于數(shù)組初始化時(shí)可以用
            A arr[10]={0};
            或者memset(arr,0,sizeof(arr));
            而盡量不要使用memset(arr,0,10*sizeof(A));
            在用第二種方法memset(arr,0,10*sizeof(A))時(shí)在A的名稱變化或者數(shù)組大小變化的時(shí)候都要修改。
            但要特別注意
            如果 A *a = new A[10];
            就一定要用memset(a,0,10*sizeof(A));因?yàn)閍是指針,所以sizeof(a)為4。


            posted @ 2010-11-23 11:41 呆人 閱讀(594) | 評(píng)論 (2)編輯 收藏

            KMP算法的一點(diǎn)理解

            KMP算法是在給定的字符串中查找某一特定的字符串(我們稱之為模式串(Pattern)).
            時(shí)間復(fù)雜度是O(m+n):m是模式串的字符數(shù),n是給定的目標(biāo)串的長(zhǎng)度。
            在寫自己見(jiàn)解之前,先給大家一個(gè)Martrix67大牛的關(guān)于KMP算法的一個(gè)鏈接
            http://www.matrix67.com/blog/archives/115

            我認(rèn)為KMP算法的難點(diǎn)在于當(dāng)匹配失效時(shí),我們要將模式串的第幾個(gè)字符與當(dāng)前目標(biāo)串的失效處進(jìn)行比較。

            我們用T來(lái)表示目標(biāo)串,P(m)來(lái)表示有m個(gè)字符的模式串。
            已知P[1...q] 與 T[s+1,s+2,....s+q]匹配。而P[q+1] 不等于T[s+q+1];
            那么T[s+q+1]應(yīng)該和P的哪個(gè)字符進(jìn)行比較呢?

            由P[1..q] = T[s+1,...s+q]對(duì)應(yīng)相等,假設(shè)T[s+q+1]要和P[k+1]進(jìn)行比較(我們是基于1的字符串,即第一個(gè)字符我們用1而不是0來(lái)表示它的下標(biāo)。)
            那么我們必須保證
            P[1...k] = T[ s+q-k+1...,s+q].
            因?yàn)樵谝欢ㄖ癙[1...q] = T[s+1,...s+q];所以P[q-k+1...q] = T[s+q-k+1,...,s+q];
            P[q-k+1,...,q]是P從q之前的k個(gè)字符,即P[q]的后面k字符。
            P[1...k]是P的前k個(gè)字符。
            所以當(dāng)我們?cè)赑[q+1]和T[s+q+1]不匹配時(shí),
            我們就是找到最大的k,使得前k個(gè)字符和后k個(gè)字符相等。

            代碼如下:

             


            long IndexOfSubString(LPCTSTR source,unsigned int start,LPCTSTR subStr)
            {
                
            long sourceLen = _tcslen(source);
                
            long subLen = _tcslen(subStr);
                
                
            long *helpArr = new long[subLen];
                memset(helpArr,
            0,sizeof(long)*subLen);
                
                helpArr[
            0=-1;

                
            long index(0);
                
            long j(-1);
                
            for(index=1;index<subLen;index++)
                
            {
                    
            while(j>0 && subStr[index] !=subStr[j+1]) j = helpArr[j];

                    
            if(subStr[index] == subStr[j+1])
                        j
            ++;

                    helpArr[index] 
            = j;
                }


                j
            =-1;
                
            for(index=start;index<sourceLen;index++)
                
            {
                    
            while(j>-1&&source[index] !=subStr[j+1]) j=helpArr[j];

                    
            if(source[index] == subStr[j+1])
                        j
            ++;
                    
            if(j==subLen-1)
                     
            return index-j;
                }

                delete[] helpArr;
                
            return -1;
            }



            posted @ 2010-11-23 11:08 呆人 閱讀(215) | 評(píng)論 (0)編輯 收藏

            在vs2008中調(diào)整lib文件輸出的位置【轉(zhuǎn)】

            在vs2008中調(diào)整lib文件輸出的位置

            默認(rèn)分類 2010-05-06 13:32:38 閱讀94 評(píng)論0   字號(hào): 訂閱

            選擇“項(xiàng)目->屬性”彈出項(xiàng)目屬性頁(yè)對(duì)話框,選擇“配置屬性->鏈接器->高級(jí)”在其中的“導(dǎo)入庫(kù)”中設(shè)置相對(duì)路徑即可。注意:相對(duì)路徑寫在第一個(gè)$符號(hào)的前面。如:..\..\dist\lib\debug\$(TargetName).lib

            如下圖:

            在vs2008中調(diào)整lib文件輸出的位置 - danshiming - danshiming的博客

            posted @ 2010-11-19 13:35 呆人 閱讀(1179) | 評(píng)論 (0)編輯 收藏

            c++的類型轉(zhuǎn)換interpret_cast,static_cast,dynamtic_cast,const_cast【轉(zhuǎn)載】

            C++的四種cast操作符的區(qū)別--類型轉(zhuǎn)換

            C++的四種cast操作符的區(qū)別
            發(fā)信站: 水木社區(qū) (Thu Jan 26 21:15:16 2006), 站內(nèi)

            聲明 by NetMD:
            并非我的原創(chuàng),來(lái)自互聯(lián)網(wǎng),且是兩篇帖子的合集,個(gè)人覺(jué)得這樣才比較完備

            ----------------------------------------------------------------------

            Q:什么是C風(fēng)格轉(zhuǎn)換?什么是static_cast, dynamic_cast 以及 reinterpret_cast?區(qū)別是什么?為什么要注意?

            A:轉(zhuǎn)換的含義是通過(guò)改變一個(gè)變量的類型為別的類型從而改變?cè)撟兞康谋硎痉绞健榱祟愋娃D(zhuǎn)換一個(gè)簡(jiǎn)單對(duì)象為另一個(gè)對(duì)象你會(huì)使用傳統(tǒng)的類型轉(zhuǎn)換操作符。比如,為了轉(zhuǎn)換一個(gè)類型為doubole的浮點(diǎn)數(shù)的指針到整型:
            代碼:
            int i;
            double d;

            i = (int) d;
            或者:

            i = int (d);

            對(duì)于具有標(biāo)準(zhǔn)定義轉(zhuǎn)換的簡(jiǎn)單類型而言工作的很好。然而,這樣的轉(zhuǎn)換符也能不分皂白的應(yīng)用于類(class)和類的指針。ANSI-C++標(biāo)準(zhǔn)定義了四個(gè)新的轉(zhuǎn)換符:'reinterpret_cast', 'static_cast', 'dynamic_cast' 和 'const_cast',目的在于控制類(class)之間的類型轉(zhuǎn)換。
            代碼:
            reinterpret_cast<new_type>(expression)
            dynamic_cast<new_type>(expression)
            static_cast<new_type>(expression)
            const_cast<new_type>(expression)


            1 reinterpret_cast

            'reinterpret_cast'轉(zhuǎn)換一個(gè)指針為其它類型的指針。它也允許從一個(gè)指針轉(zhuǎn)換為整數(shù)類型。反之亦然。(譯注:是指針具體的地址值作為整數(shù)值?)
            這個(gè)操作符能夠在非相關(guān)的類型之間轉(zhuǎn)換。操作結(jié)果只是簡(jiǎn)單的從一個(gè)指針到別的指針的值的二進(jìn)制拷貝。在類型之間指向的內(nèi)容不做任何類型的檢查和轉(zhuǎn)換。

            如果情況是從一個(gè)指針到整型的拷貝,內(nèi)容的解釋是系統(tǒng)相關(guān)的,所以任何的實(shí)現(xiàn)都不是方便的。一個(gè)轉(zhuǎn)換到足夠大的整型能夠包含它的指針是能夠轉(zhuǎn)換回有效的指針的。

            代碼:
            class A {};
            class B {};

            A * a = new A;
            B * b = reinterpret_cast<B *>(a);
            'reinterpret_cast'就像傳統(tǒng)的類型轉(zhuǎn)換一樣對(duì)待所有指針的類型轉(zhuǎn)換。

            2 static_cast

            'static_cast'允許執(zhí)行任意的隱式轉(zhuǎn)換和相反轉(zhuǎn)換動(dòng)作。(即使它是不允許隱式的)

            應(yīng)用到類的指針上,意思是說(shuō)它允許子類類型的指針轉(zhuǎn)換為父類類型的指針(這是一個(gè)有效的隱式轉(zhuǎn)換),同時(shí),也能夠執(zhí)行相反動(dòng)作:轉(zhuǎn)換父類為它的子類。

            在這最后例子里,被轉(zhuǎn)換的父類沒(méi)有被檢查是否與目的類型相一致。
            代碼:
            class Base {};
            class Derived : public Base {};

            Base *a    = new Base;
            Derived *b = static_cast<Derived *>(a);
            'static_cast'除了操作類型指針,也能用于執(zhí)行類型定義的顯式的轉(zhuǎn)換,以及基礎(chǔ)類型之間的標(biāo)準(zhǔn)轉(zhuǎn)換:

            代碼:
            double d = 3.14159265;
            int    i = static_cast<int>(d);

            3 dynamic_cast

            'dynamic_cast'只用于對(duì)象的指針和引用。當(dāng)用于多態(tài)類型時(shí),它允許任意的隱式類型轉(zhuǎn)換以及相反過(guò)程。不過(guò),與static_cast不同,在后一種情況里(注:即隱式轉(zhuǎn)換的相反過(guò)程),dynamic_cast會(huì)檢查操作是否有效。也就是說(shuō),它會(huì)檢查轉(zhuǎn)換是否會(huì)返回一個(gè)被請(qǐng)求的有效的完整對(duì)象。
            檢測(cè)在運(yùn)行時(shí)進(jìn)行。如果被轉(zhuǎn)換的指針不是一個(gè)被請(qǐng)求的有效完整的對(duì)象指針,返回值為NULL.
            代碼:
            class Base { virtual dummy() {} };
            class Derived : public Base {};

            Base* b1 = new Derived;
            Base* b2 = new Base;

            Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
            Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'

            如果一個(gè)引用類型執(zhí)行了類型轉(zhuǎn)換并且這個(gè)轉(zhuǎn)換是不可能的,一個(gè)bad_cast的異常類型被拋出:
            代碼:
            class Base { virtual dummy() {} };
            class Derived : public Base { };

            Base* b1 = new Derived;
            Base* b2 = new Base;

            Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
            Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown

            4 const_cast

            這個(gè)轉(zhuǎn)換類型操縱傳遞對(duì)象的const屬性,或者是設(shè)置或者是移除:
            代碼:
            class C {};

            const C *a = new C;

            C *b = const_cast<C *>(a);
            其它三種操作符是不能修改一個(gè)對(duì)象的常量性的。
            注意:'const_cast'也能改變一個(gè)類型的volatile qualifier。

            --------------------------------------------------------------------

            C++的4種類型轉(zhuǎn)換

                一、C 風(fēng)格(C-style)強(qiáng)制轉(zhuǎn)型如下:

                (T) expression // cast expression to be of type T
                函數(shù)風(fēng)格(Function-style)強(qiáng)制轉(zhuǎn)型使用這樣的語(yǔ)法:
                T(expression) // cast expression to be of type T
                這兩種形式之間沒(méi)有本質(zhì)上的不同,它純粹就是一個(gè)把括號(hào)放在哪的問(wèn)題。我把這兩種形式稱為舊風(fēng)格(old-style)的強(qiáng)制轉(zhuǎn)型。

               二、 C++的四種強(qiáng)制轉(zhuǎn)型形式:

              C++ 同時(shí)提供了四種新的強(qiáng)制轉(zhuǎn)型形式(通常稱為新風(fēng)格的或 C++ 風(fēng)格的強(qiáng)制轉(zhuǎn)型):
              const_cast(expression)
              dynamic_cast(expression)
              reinterpret_cast(expression)
              static_cast(expression)

              每一種適用于特定的目的:

              ·dynamic_cast 主要用于執(zhí)行“安全的向下轉(zhuǎn)型(safe downcasting)”,也就是說(shuō),要確定一個(gè)對(duì)象是否是一個(gè)繼承體系中的一個(gè)特定類型。它是唯一不能用舊風(fēng)格語(yǔ)法執(zhí)行的強(qiáng)制轉(zhuǎn)型,也是唯一可能有重大運(yùn)行時(shí)代價(jià)的強(qiáng)制轉(zhuǎn)型。
                
                ·static_cast 可以被用于強(qiáng)制隱型轉(zhuǎn)換(例如,non-const 對(duì)象轉(zhuǎn)型為 const 對(duì)象,int 轉(zhuǎn)型為 double,等等),它還可以用于很多這樣的轉(zhuǎn)換的反向轉(zhuǎn)換(例如,void* 指針轉(zhuǎn)型為有類型指針,基類指針轉(zhuǎn)型為派生類指針),但是它不能將一個(gè) const 對(duì)象轉(zhuǎn)型為 non-const 對(duì)象(只有 const_cast 能做到),它最接近于C-style的轉(zhuǎn)換。
                
              ·const_cast 一般用于強(qiáng)制消除對(duì)象的常量性。它是唯一能做到這一點(diǎn)的 C++ 風(fēng)格的強(qiáng)制轉(zhuǎn)型。

              ·reinterpret_cast 是特意用于底層的強(qiáng)制轉(zhuǎn)型,導(dǎo)致實(shí)現(xiàn)依賴(implementation-dependent)(就是說(shuō),不可移植)的結(jié)果,例如,將一個(gè)指針轉(zhuǎn)型為一個(gè)整數(shù)。這樣的強(qiáng)制轉(zhuǎn)型在底層代碼以外應(yīng)該極為罕見(jiàn)。
              
              舊風(fēng)格的強(qiáng)制轉(zhuǎn)型依然合法,但是新的形式更可取。首先,在代碼中它們更容易識(shí)別(無(wú)論是人還是像 grep 這樣的工具都是如此),這樣就簡(jiǎn)化了在代碼中尋找類型系統(tǒng)被破壞的地方的過(guò)程。第二,更精確地指定每一個(gè)強(qiáng)制轉(zhuǎn)型的目的,使得編譯器診斷使用錯(cuò)誤成為可能。例如,如果你試圖使用一個(gè) const_cast 以外的新風(fēng)格強(qiáng)制轉(zhuǎn)型來(lái)消除常量性,你的代碼將無(wú)法編譯。

            ==  
            ==  dynamic_cast .vs. static_cast
            ==

            class B { ... };
            class D : public B { ... };

            void f(B* pb)
            {
               D* pd1 = dynamic_cast<D*>(pb);
               D* pd2 = static_cast<D*>(pb);
            }

            If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0.

            If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

                即dynamic_cast可用于繼承體系中的向下轉(zhuǎn)型,即將基類指針轉(zhuǎn)換為派生類指針,比static_cast更嚴(yán)格更安全。dynamic_cast在執(zhí)行效率上比static_cast要差一些,但static_cast在更寬上范圍內(nèi)可以完成映射,這種不加限制的映射伴隨著不安全性.static_cast覆蓋的變換類型除類層次的靜態(tài)導(dǎo)航以外,還包括無(wú)映射變換,窄化變換(這種變換會(huì)導(dǎo)致對(duì)象切片,丟失信息),用VOID*的強(qiáng)制變換,隱式類型變換等...


            ==
            ==  static_cast .vs. reinterpret_cast
            ==

                reinterpret_cast是為了映射到一個(gè)完全不同類型的意思,這個(gè)關(guān)鍵詞在我們需要把類型映射回原有類型時(shí)用到它.我們映射到的類型僅僅是為了故弄玄虛和其他目的,這是所有映射中最危險(xiǎn)的.(這句話是C++編程思想中的原話)

                static_cast 和 reinterpret_cast 操作符修改了操作數(shù)類型. 它們不是互逆的; static_cast 在編譯時(shí)使用類型信息執(zhí)行轉(zhuǎn)換, 在轉(zhuǎn)換執(zhí)行必要的檢測(cè)(諸如指針越界計(jì)算, 類型檢查). 其操作數(shù)相對(duì)是安全的. 另一方面, reinterpret_cast 僅僅是重新解釋了給出的對(duì)象的比特模型而沒(méi)有進(jìn)行二進(jìn)制轉(zhuǎn)換, 例子如下:

                int n=9; double d=static_cast < double > (n);

                上面的例子中, 我們將一個(gè)變量從 int 轉(zhuǎn)換到 double. 這些類型的二進(jìn)制表達(dá)式是不同的. 要將整數(shù) 9 轉(zhuǎn)換到 雙精度整數(shù) 9, static_cast 需要正確地為雙精度整數(shù) d 補(bǔ)足比特位. 其結(jié)果為 9.0. 而reinterpret_cast 的行為卻不同:

                int n=9;
                double d=reinterpret_cast<double & > (n);

                這次, 結(jié)果有所不同. 在進(jìn)行計(jì)算以后, d 包含無(wú)用值. 這是因?yàn)?reinterpret_cast 僅僅是復(fù)制 n 的比特位到 d, 沒(méi)有進(jìn)行必要的分析.

            posted @ 2010-11-15 15:01 呆人 閱讀(1547) | 評(píng)論 (0)編輯 收藏

            printf中變參的實(shí)現(xiàn)

            #ifdef _M_CEE_PURE
            typedef System::ArgIterator va_list;
            #else
            typedef char *  va_list;
            #endif /* _M_CEE_PURE */

            我們使用 typedef char* va_list;//va_list是一個(gè)指向char的函數(shù)指針

            #define _ADDRESSOF(v)   ( &reinterpret_cast<const char &>(v) )
            _ADDRESSOF(v)的作用是取得v變量的地址。

            #define _INTSIZEOF(n)   ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )
            以int所占的字節(jié)為標(biāo)準(zhǔn)進(jìn)行對(duì)其操作。
            如果int占四字節(jié),則以四字節(jié)對(duì)齊為標(biāo)準(zhǔn)讀取數(shù)據(jù)。

            在stdarg.h中有下面三個(gè)宏的定義
            #define va_start
            _crt_va_start
            #define va_arg
            _crt_va_arg
            #define va_end
            _crt_va_end
            紅色標(biāo)注的宏是用戶直接使用的宏,下面我們來(lái)看一下他們各自的實(shí)現(xiàn),即綠色標(biāo)注的部分。

            在vadefs.h中有上述綠色標(biāo)注部分的實(shí)現(xiàn)。

            #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
            #define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
            #define _crt_va_end(ap)      ( ap = (va_list)0 )

            解析
            1.   #define _crt_va_start(ap,v)  ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
            (va_list)_ADDRESSOF(v)得到v的地址
            INTSIZEOF(v) 字節(jié)對(duì)齊后v的大小
            最后ap指向v的下一個(gè)對(duì)象的指針,即所以ap 就指向v后面的參數(shù)的起始地址。

            2.#define _crt_va_arg(ap,t)    ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
            分為以下幾個(gè)step解析:
            (1) ap += _INTSIZEOF(t) 指向類型為t的下一個(gè)參數(shù)的地址。
            (2) (ap += _INTSIZEOF(t))- _INTSIZEOF(t) 指向當(dāng)前類型為t的參數(shù)的指針
            (3)(t*)((ap += _INTSIZEOF(t))- _INTSIZEOF(t))將當(dāng)前指針轉(zhuǎn)換成t類型的指針
            (4)( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )取得當(dāng)前指針的值。

            3.#define _crt_va_end(ap)      ( ap = (va_list)0 )
            將va_list置成無(wú)效指針。

            以上是printf()變參的實(shí)現(xiàn)過(guò)程







            posted @ 2010-11-11 17:25 呆人 閱讀(510) | 評(píng)論 (0)編輯 收藏

            printf的實(shí)現(xiàn)【轉(zhuǎn)載】

            va_list,va_start,va_arg,va_end——變長(zhǎng)參數(shù)實(shí)現(xiàn)機(jī)制
            2009年10月28日 星期三 11:09 P.M.

            什么是變長(zhǎng)參數(shù)?

            所謂含有變長(zhǎng)參數(shù)的函數(shù)是指該函數(shù)可以接受可變數(shù)目的形參。例如我們都非常熟悉的

            printf,scanf等等。

            2:變長(zhǎng)參數(shù)如何實(shí)現(xiàn)?

            首先來(lái)看下面這樣一個(gè)例子:

            #include<stdio.h>
            #include<stdarg.h>
            #include<string.h>

            void demo(char *msg,...)
            {
            va_list argp;
            int arg_number=0;
            char *para = msg;
            va_start(argp,msg);
            while(1)
            {
               if ( strcmp( para, "\0") != 0 )
               {
                arg_number++;   
                printf("parameter %d is: %s\n",arg_number,para);
               
               }
               else
                break;
               para = va_arg(argp,char *);
            }
            va_end(argp);
            }
            int main()
            {
            demo("Hello","World","\0");
            system("pause");
            return 0;
            }

            實(shí)現(xiàn)這樣一個(gè)函數(shù)要在內(nèi)部使用va_list,va_start,va_arg,va_end,這些都是定義在

            stdarg.h中的宏。

            va_list是定義了一個(gè)保存函數(shù)參數(shù)的數(shù)據(jù)結(jié)構(gòu)。

            va_start(argp,msg)是將argp指向第一個(gè)可變參數(shù),而msg是最后一個(gè)確定的參數(shù)。

            最后一個(gè)確定的參數(shù)的含義是指它以后的參數(shù)都是可變參數(shù),如果有下面的函數(shù)聲明

            void demo(char *msg1,char *msg2,...)

            那么這里的最后一個(gè)確定參數(shù)就是msg2。

            va_arg(argp,char *)返回當(dāng)前參數(shù)的值,類型為char *,然后將argp指向下一個(gè)變長(zhǎng)參

            數(shù)。從這一步可以看出來(lái)我們可以通過(guò)va_start和va_arg遍歷所有的變長(zhǎng)參數(shù)。

            va_end 將argp的值置為0。


            下面我們看看上述幾個(gè)宏在visual c++.net 2003 中的實(shí)現(xiàn)方法。首先是va_list的實(shí)現(xiàn)

            #ifdef   _M_ALPHA
            typedef struct {
                     char *a0;        /* pointer to first homed integer argument */
                     int offset;      /* byte offset of next parameter */
            } va_list;
            #else
            typedef char *   va_list;
            #endif


            可以看到va_list實(shí)際上是一個(gè)機(jī)器類型相關(guān)的宏,除了alpha機(jī)器以外,其他機(jī)器類

            型都被定義為一個(gè)char類型的指針變量,之所以定義為char *是因?yàn)榭梢杂迷撟兞恐?/p>

            地址也就是逐字節(jié)對(duì)參數(shù)進(jìn)行遍歷。

            從上面可以看到,這些宏的實(shí)現(xiàn)都是和機(jī)器相關(guān)的,下面是大家常用的IX86機(jī)器下宏的

            相關(guān)定義。

            #elif    defined(_M_IX86)

            #define _INTSIZEOF(n)    ( (sizeof(n) + sizeof(int) - 1) & ~(sizeof(int) - 1) )

            #define va_start(ap,v)   ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )
            #define va_arg(ap,t)     ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )
            #define va_end(ap)       ( ap = (va_list)0 )

            #ifdef   __cplusplus
            #define _ADDRESSOF(v)    ( &reinterpret_cast<const char &>(v) )
            #else
            #define _ADDRESSOF(v)    ( &(v) )
            #endif

            首先看_INTSIZEOF(n)

            我們知道對(duì)于IX86,sizeof(int)一定是4的整數(shù)倍,所以~(sizeof(int) - 1) )的值一定是

            右面[sizeof(n)-1]/2位為0,整個(gè)這個(gè)宏也就是保證了右面[sizeof(n)-1]/2位為0,其余位置

            為1,所以_INTSIZEOF(n)的值只有可能是2,4,8,16,......等等,實(shí)際上是實(shí)現(xiàn)了字節(jié)對(duì)齊。

            #define va_start(ap,v)   ( ap = (va_list)_ADDRESSOF(v) + _INTSIZEOF(v) )

            所以va_start(ap,v)的作用就很明了了,_ADDRESSOF(v)定義了v的起始地址,_INTSIZEOF(v)定義了v所

            占用的內(nèi)存,所以ap 就指向v后面的參數(shù)的起始地址。

            #define va_arg(ap,t)     ( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )

            ap += _INTSIZEOF(t) 使ap指向了后面一個(gè)參數(shù)的地址

            而( *(t *)((ap += _INTSIZEOF(t)) - _INTSIZEOF(t)) )相當(dāng)于返回了目前t類型的參數(shù)的值。

            #define va_end(ap)       ( ap = (va_list)0 )

            將變量ap 的值置為0。

            通過(guò)上述分析,再次印證了我么前面對(duì)可變參數(shù)實(shí)現(xiàn)的解釋。


            因此我們可以總結(jié)出變長(zhǎng)參數(shù)函數(shù)的一般實(shí)現(xiàn)方法:

            1:聲明原型,形如void demo(char *msg,...),注意變長(zhǎng)參數(shù)的原型聲明中至少要含有

            一個(gè)確定參數(shù)。

            2:用va_list定義保存函數(shù)參數(shù)的數(shù)據(jù)結(jié)構(gòu),可以理解為一個(gè)指針變量(稍后會(huì)解釋)。

            3:用va_start將上一步定義的變量指向第一個(gè)可變參數(shù)。

            4:用va_arg遍歷所有的可變參數(shù)。

            5:用va_end將指針變量持有的地址值置為0。


            posted @ 2010-11-11 17:23 呆人 閱讀(1839) | 評(píng)論 (0)編輯 收藏

            c++類型轉(zhuǎn)換操作【轉(zhuǎn)載】

            C++的四種cast操作符的區(qū)別--類型轉(zhuǎn)換

            C++的四種cast操作符的區(qū)別
            發(fā)信站: 水木社區(qū) (Thu Jan 26 21:15:16 2006), 站內(nèi)

            聲明 by NetMD:
            并非我的原創(chuàng),來(lái)自互聯(lián)網(wǎng),且是兩篇帖子的合集,個(gè)人覺(jué)得這樣才比較完備

            ----------------------------------------------------------------------

            Q:什么是C風(fēng)格轉(zhuǎn)換?什么是static_cast, dynamic_cast 以及 reinterpret_cast?區(qū)別是什么?為什么要注意?

            A:轉(zhuǎn)換的含義是通過(guò)改變一個(gè)變量的類型為別的類型從而改變?cè)撟兞康谋硎痉绞健榱祟愋娃D(zhuǎn)換一個(gè)簡(jiǎn)單對(duì)象為另一個(gè)對(duì)象你會(huì)使用傳統(tǒng)的類型轉(zhuǎn)換操作符。比如,為了轉(zhuǎn)換一個(gè)類型為doubole的浮點(diǎn)數(shù)的指針到整型:
            代碼:
            int i;
            double d;

            i = (int) d;
            或者:

            i = int (d);

            對(duì)于具有標(biāo)準(zhǔn)定義轉(zhuǎn)換的簡(jiǎn)單類型而言工作的很好。然而,這樣的轉(zhuǎn)換符也能不分皂白的應(yīng)用于類(class)和類的指針。ANSI-C++標(biāo)準(zhǔn)定義了四個(gè)新的轉(zhuǎn)換符:'reinterpret_cast', 'static_cast', 'dynamic_cast' 和 'const_cast',目的在于控制類(class)之間的類型轉(zhuǎn)換。
            代碼:
            reinterpret_cast<new_type>(expression)
            dynamic_cast<new_type>(expression)
            static_cast<new_type>(expression)
            const_cast<new_type>(expression)


            1 reinterpret_cast

            'reinterpret_cast'轉(zhuǎn)換一個(gè)指針為其它類型的指針。它也允許從一個(gè)指針轉(zhuǎn)換為整數(shù)類型。反之亦然。(譯注:是指針具體的地址值作為整數(shù)值?)
            這個(gè)操作符能夠在非相關(guān)的類型之間轉(zhuǎn)換。操作結(jié)果只是簡(jiǎn)單的從一個(gè)指針到別的指針的值的二進(jìn)制拷貝。在類型之間指向的內(nèi)容不做任何類型的檢查和轉(zhuǎn)換。

            如果情況是從一個(gè)指針到整型的拷貝,內(nèi)容的解釋是系統(tǒng)相關(guān)的,所以任何的實(shí)現(xiàn)都不是方便的。一個(gè)轉(zhuǎn)換到足夠大的整型能夠包含它的指針是能夠轉(zhuǎn)換回有效的指針的。

            代碼:
            class A {};
            class B {};

            A * a = new A;
            B * b = reinterpret_cast<B *>(a);
            'reinterpret_cast'就像傳統(tǒng)的類型轉(zhuǎn)換一樣對(duì)待所有指針的類型轉(zhuǎn)換。

            2 static_cast

            'static_cast'允許執(zhí)行任意的隱式轉(zhuǎn)換和相反轉(zhuǎn)換動(dòng)作。(即使它是不允許隱式的)

            應(yīng)用到類的指針上,意思是說(shuō)它允許子類類型的指針轉(zhuǎn)換為父類類型的指針(這是一個(gè)有效的隱式轉(zhuǎn)換),同時(shí),也能夠執(zhí)行相反動(dòng)作:轉(zhuǎn)換父類為它的子類。

            在這最后例子里,被轉(zhuǎn)換的父類沒(méi)有被檢查是否與目的類型相一致。
            代碼:
            class Base {};
            class Derived : public Base {};

            Base *a    = new Base;
            Derived *b = static_cast<Derived *>(a);
            'static_cast'除了操作類型指針,也能用于執(zhí)行類型定義的顯式的轉(zhuǎn)換,以及基礎(chǔ)類型之間的標(biāo)準(zhǔn)轉(zhuǎn)換:

            代碼:
            double d = 3.14159265;
            int    i = static_cast<int>(d);

            3 dynamic_cast

            'dynamic_cast'只用于對(duì)象的指針和引用。當(dāng)用于多態(tài)類型時(shí),它允許任意的隱式類型轉(zhuǎn)換以及相反過(guò)程。不過(guò),與static_cast不同,在后一種情況里(注:即隱式轉(zhuǎn)換的相反過(guò)程),dynamic_cast會(huì)檢查操作是否有效。也就是說(shuō),它會(huì)檢查轉(zhuǎn)換是否會(huì)返回一個(gè)被請(qǐng)求的有效的完整對(duì)象。
            檢測(cè)在運(yùn)行時(shí)進(jìn)行。如果被轉(zhuǎn)換的指針不是一個(gè)被請(qǐng)求的有效完整的對(duì)象指針,返回值為NULL.
            代碼:
            class Base { virtual dummy() {} };
            class Derived : public Base {};

            Base* b1 = new Derived;
            Base* b2 = new Base;

            Derived* d1 = dynamic_cast<Derived *>(b1);          // succeeds
            Derived* d2 = dynamic_cast<Derived *>(b2);          // fails: returns 'NULL'

            如果一個(gè)引用類型執(zhí)行了類型轉(zhuǎn)換并且這個(gè)轉(zhuǎn)換是不可能的,一個(gè)bad_cast的異常類型被拋出:
            代碼:
            class Base { virtual dummy() {} };
            class Derived : public Base { };

            Base* b1 = new Derived;
            Base* b2 = new Base;

            Derived d1 = dynamic_cast<Derived &*>(b1);          // succeeds
            Derived d2 = dynamic_cast<Derived &*>(b2);          // fails: exception thrown

            4 const_cast

            這個(gè)轉(zhuǎn)換類型操縱傳遞對(duì)象的const屬性,或者是設(shè)置或者是移除:
            代碼:
            class C {};

            const C *a = new C;

            C *b = const_cast<C *>(a);
            其它三種操作符是不能修改一個(gè)對(duì)象的常量性的。
            注意:'const_cast'也能改變一個(gè)類型的volatile qualifier。

            --------------------------------------------------------------------

            C++的4種類型轉(zhuǎn)換

                一、C 風(fēng)格(C-style)強(qiáng)制轉(zhuǎn)型如下:

                (T) expression // cast expression to be of type T
                函數(shù)風(fēng)格(Function-style)強(qiáng)制轉(zhuǎn)型使用這樣的語(yǔ)法:
                T(expression) // cast expression to be of type T
                這兩種形式之間沒(méi)有本質(zhì)上的不同,它純粹就是一個(gè)把括號(hào)放在哪的問(wèn)題。我把這兩種形式稱為舊風(fēng)格(old-style)的強(qiáng)制轉(zhuǎn)型。

               二、 C++的四種強(qiáng)制轉(zhuǎn)型形式:

              C++ 同時(shí)提供了四種新的強(qiáng)制轉(zhuǎn)型形式(通常稱為新風(fēng)格的或 C++ 風(fēng)格的強(qiáng)制轉(zhuǎn)型):
              const_cast(expression)
              dynamic_cast(expression)
              reinterpret_cast(expression)
              static_cast(expression)

              每一種適用于特定的目的:

              ·dynamic_cast 主要用于執(zhí)行“安全的向下轉(zhuǎn)型(safe downcasting)”,也就是說(shuō),要確定一個(gè)對(duì)象是否是一個(gè)繼承體系中的一個(gè)特定類型。它是唯一不能用舊風(fēng)格語(yǔ)法執(zhí)行的強(qiáng)制轉(zhuǎn)型,也是唯一可能有重大運(yùn)行時(shí)代價(jià)的強(qiáng)制轉(zhuǎn)型。
                
                ·static_cast 可以被用于強(qiáng)制隱型轉(zhuǎn)換(例如,non-const 對(duì)象轉(zhuǎn)型為 const 對(duì)象,int 轉(zhuǎn)型為 double,等等),它還可以用于很多這樣的轉(zhuǎn)換的反向轉(zhuǎn)換(例如,void* 指針轉(zhuǎn)型為有類型指針,基類指針轉(zhuǎn)型為派生類指針),但是它不能將一個(gè) const 對(duì)象轉(zhuǎn)型為 non-const 對(duì)象(只有 const_cast 能做到),它最接近于C-style的轉(zhuǎn)換。
                
              ·const_cast 一般用于強(qiáng)制消除對(duì)象的常量性。它是唯一能做到這一點(diǎn)的 C++ 風(fēng)格的強(qiáng)制轉(zhuǎn)型。

              ·reinterpret_cast 是特意用于底層的強(qiáng)制轉(zhuǎn)型,導(dǎo)致實(shí)現(xiàn)依賴(implementation-dependent)(就是說(shuō),不可移植)的結(jié)果,例如,將一個(gè)指針轉(zhuǎn)型為一個(gè)整數(shù)。這樣的強(qiáng)制轉(zhuǎn)型在底層代碼以外應(yīng)該極為罕見(jiàn)。
              
              舊風(fēng)格的強(qiáng)制轉(zhuǎn)型依然合法,但是新的形式更可取。首先,在代碼中它們更容易識(shí)別(無(wú)論是人還是像 grep 這樣的工具都是如此),這樣就簡(jiǎn)化了在代碼中尋找類型系統(tǒng)被破壞的地方的過(guò)程。第二,更精確地指定每一個(gè)強(qiáng)制轉(zhuǎn)型的目的,使得編譯器診斷使用錯(cuò)誤成為可能。例如,如果你試圖使用一個(gè) const_cast 以外的新風(fēng)格強(qiáng)制轉(zhuǎn)型來(lái)消除常量性,你的代碼將無(wú)法編譯。

            ==  
            ==  dynamic_cast .vs. static_cast
            ==

            class B { ... };
            class D : public B { ... };

            void f(B* pb)
            {
               D* pd1 = dynamic_cast<D*>(pb);
               D* pd2 = static_cast<D*>(pb);
            }

            If pb really points to an object of type D, then pd1 and pd2 will get the same value. They will also get the same value if pb == 0.

            If pb points to an object of type B and not to the complete D class, then dynamic_cast will know enough to return zero. However, static_cast relies on the programmer’s assertion that pb points to an object of type D and simply returns a pointer to that supposed D object.

                即dynamic_cast可用于繼承體系中的向下轉(zhuǎn)型,即將基類指針轉(zhuǎn)換為派生類指針,比static_cast更嚴(yán)格更安全。dynamic_cast在執(zhí)行效率上比static_cast要差一些,但static_cast在更寬上范圍內(nèi)可以完成映射,這種不加限制的映射伴隨著不安全性.static_cast覆蓋的變換類型除類層次的靜態(tài)導(dǎo)航以外,還包括無(wú)映射變換,窄化變換(這種變換會(huì)導(dǎo)致對(duì)象切片,丟失信息),用VOID*的強(qiáng)制變換,隱式類型變換等...


            ==
            ==  static_cast .vs. reinterpret_cast
            ==

                reinterpret_cast是為了映射到一個(gè)完全不同類型的意思,這個(gè)關(guān)鍵詞在我們需要把類型映射回原有類型時(shí)用到它.我們映射到的類型僅僅是為了故弄玄虛和其他目的,這是所有映射中最危險(xiǎn)的.(這句話是C++編程思想中的原話)

                static_cast 和 reinterpret_cast 操作符修改了操作數(shù)類型. 它們不是互逆的; static_cast 在編譯時(shí)使用類型信息執(zhí)行轉(zhuǎn)換, 在轉(zhuǎn)換執(zhí)行必要的檢測(cè)(諸如指針越界計(jì)算, 類型檢查). 其操作數(shù)相對(duì)是安全的. 另一方面, reinterpret_cast 僅僅是重新解釋了給出的對(duì)象的比特模型而沒(méi)有進(jìn)行二進(jìn)制轉(zhuǎn)換, 例子如下:

                int n=9; double d=static_cast < double > (n);

                上面的例子中, 我們將一個(gè)變量從 int 轉(zhuǎn)換到 double. 這些類型的二進(jìn)制表達(dá)式是不同的. 要將整數(shù) 9 轉(zhuǎn)換到 雙精度整數(shù) 9, static_cast 需要正確地為雙精度整數(shù) d 補(bǔ)足比特位. 其結(jié)果為 9.0. 而reinterpret_cast 的行為卻不同:

                int n=9;
                double d=reinterpret_cast<double & > (n);

                這次, 結(jié)果有所不同. 在進(jìn)行計(jì)算以后, d 包含無(wú)用值. 這是因?yàn)?reinterpret_cast 僅僅是復(fù)制 n 的比特位到 d, 沒(méi)有進(jìn)行必要的分析.

            posted @ 2010-11-11 16:51 呆人 閱讀(187) | 評(píng)論 (0)編輯 收藏

            c++中各操作符優(yōu)先級(jí)一覽表【轉(zhuǎn)載】

            C語(yǔ)言程序設(shè)計(jì) 運(yùn)算符的優(yōu)先級(jí)與結(jié)合性

             C運(yùn)算符的優(yōu)先級(jí)與結(jié)合

            優(yōu)先級(jí)

            運(yùn)算符

            含義

            參與運(yùn)算對(duì)象的數(shù)目

            結(jié)合方向

             1

            ( )
            [ ]
            ->
            .

            圓括號(hào)運(yùn)算符
            下標(biāo)運(yùn)算符
            指向結(jié)構(gòu)體成員運(yùn)算符
            結(jié)構(gòu)體成員運(yùn)算符


            雙目運(yùn)算符
            雙目運(yùn)算符
            雙目運(yùn)算符

            自左至右

            2


            ~
            ++
            --
            -
            (
            類型)


            sizeof

            邏輯非運(yùn)算符
            按位取反運(yùn)算符
            自增運(yùn)算符
            自減運(yùn)算符
            負(fù)號(hào)運(yùn)算符
            類型轉(zhuǎn)換運(yùn)算符
            指針運(yùn)算符
            取地址運(yùn)算符
            求類型長(zhǎng)度運(yùn)算符

            單目運(yùn)算符

            自右至左

            3


            /
            %

            乘法運(yùn)算符
            除法運(yùn)算符
            求余運(yùn)算符

            雙目運(yùn)算符

            自左至右

            4


            加法運(yùn)算符
            減法運(yùn)算符

            雙目運(yùn)算符

            自左至右

            5

            <<
            >>

            左移運(yùn)算符
            右移運(yùn)算符

            雙目運(yùn)算符

            自左至右

            6

            <
            <=
            >
            >=

            關(guān)系運(yùn)算符

            雙目運(yùn)算符

            自左至右

            7

            ==
            !=

            判等運(yùn)算符
            判不等運(yùn)算符

            雙目運(yùn)算符

            自左至右

            8

            按位與運(yùn)算符

            雙目運(yùn)算符

            自左至右

            9

            按位異或運(yùn)算符

            雙目運(yùn)算符

            自左至右

            10

            |

            按位或運(yùn)算符

            雙目運(yùn)算符

            自左至右

            11

            &&

            邏輯與運(yùn)算符

            雙目運(yùn)算符

            自左至右

            12

            ||

            邏輯或運(yùn)算符

            雙目運(yùn)算符

            自左至右

            13

            ?:

            條件運(yùn)算符

            三目運(yùn)算符

            自右至左

            14


            +=
            -=
            *=
            /

            %

            >>=
            <<=
            &=
            =
            |

            賦值運(yùn)算符

            雙目運(yùn)算符

            自右至左

            15

            逗號(hào)運(yùn)算符
            (順序求值運(yùn)算符)

             

            自左至右

















































            posted @ 2010-11-11 10:51 呆人 閱讀(559) | 評(píng)論 (0)編輯 收藏

            編譯項(xiàng)目跟蹤文檔(三)

            這里主要寫一下“-”的處理。
            詞法分析階段,我們可以把“-”解釋成減號(hào)或者是表示是一個(gè)負(fù)數(shù)
            那么怎么來(lái)區(qū)分這兩種情況呢?
            我的做法(有點(diǎn)投機(jī)取巧,個(gè)人感覺(jué)不是很好,可是又想不出更好的來(lái),希望大家能給我更好的建議):

            詞法分析階段,將所有所得的單詞(Token)放到 m_tokens[]中。

            如果碰到"-",將他解析成__SUB__TOKEN(減號(hào)),放到m_tokens[index1] = __SUB__TOKEN;

            解析到數(shù)字單詞(__NUM_TOKEN)時(shí),判斷它的前一個(gè)單詞是否是__SUB__TOKEN.

            1.如果是__SUB__TOKEN,則判斷__SUB__TOKEN的前一個(gè)單詞是否是(算術(shù)運(yùn)算符:+,-,*,/以及是否是(,{,=)(*)
                
                1.1如果(*)中的任意一個(gè)則將前一個(gè)__SUB__TOKEN識(shí)別成負(fù)號(hào),把當(dāng)前的__NUM__TOKEN的值取反,并用__NUM_TOKEN覆蓋它前面的__SUB_TOKEN.

                1.2 如果不是(*)中的任意一個(gè),則認(rèn)為前一個(gè)__SUB_TOKEN就是減號(hào)。

            2.如果不是__SUB__TOKEN,不予處理。

            不知道我又沒(méi)有表述清楚,本來(lái)有一個(gè)流程圖,可是不知道怎么貼過(guò)來(lái),見(jiàn)諒!! 

            posted @ 2010-11-05 09:18 呆人 閱讀(186) | 評(píng)論 (0)編輯 收藏

            編譯項(xiàng)目跟蹤文檔(二)

            今天發(fā)現(xiàn)了自己一直都理解錯(cuò)的一個(gè)問(wèn)題:邏輯運(yùn)算符的優(yōu)先級(jí)問(wèn)題。
            取反的優(yōu)先級(jí)最高
            &&的優(yōu)先級(jí)次之
            ||的優(yōu)先級(jí)最低。

            今天要將循環(huán)語(yǔ)句翻譯成中間代碼。由于一直沒(méi)有找到很明確的關(guān)于條件表達(dá)式的語(yǔ)法定義。在此將自己定義的語(yǔ)法結(jié)構(gòu)記下啦,希望大家多多指教:

            IF(BoolExp)
            {
              StmtSequence
            }
            ELSE
            {
               StmtSequence
            }

            BoolExp ----> BoolTerm |  || BoolTerm
            BoolTerm ----> BoolFactor | && BoolFactor
            BoolFactor ----> (BoolExp) | RelExp | !BoolExp

            RelExp ----> ArithExp relOp ArithExp
            ArithExp ----> ArithTerm | +ArithTerm | -ArithTerm
            ArithTerm ----> ArithFactor | *ArithFactor | /ArithFactor
            ArithFactor -----> ID | NUM| Func| (ArithExp)

            relOp ----->  > | >= | < |<= | == | !=

            StmtSequence -> Stmt | ;Stmt
            Stmt -> AssignStmt | DeclareStmt | ConditionalStmt | CallFuncStmt
            至于更細(xì)節(jié)的地方在此不做贅述。

            對(duì)于結(jié)構(gòu)產(chǎn)生式的左邊每一個(gè)非終結(jié)符有一個(gè)對(duì)應(yīng)的方法。根據(jù)語(yǔ)法定義調(diào)用即可。
            如果需要代碼請(qǐng)留言,并注明郵箱,發(fā)給你!!

            生成控制流代碼時(shí)采用回填技術(shù)。我覺(jué)得龍書《Compilers,Principles,Techniques,&Tools 》second Editon對(duì)于回填技術(shù)講的很清楚。



            posted @ 2010-11-02 16:10 呆人 閱讀(1333) | 評(píng)論 (1)編輯 收藏

            僅列出標(biāo)題
            共6頁(yè): 1 2 3 4 5 6 
            <2025年6月>
            25262728293031
            1234567
            891011121314
            15161718192021
            22232425262728
            293012345

            導(dǎo)航

            統(tǒng)計(jì)

            常用鏈接

            留言簿(1)

            隨筆分類

            隨筆檔案

            搜索

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            午夜视频久久久久一区| AV狠狠色丁香婷婷综合久久| 久久综合九色综合久99| 久久无码AV一区二区三区| 久久国产热精品波多野结衣AV| 色综合久久天天综合| 久久人人爽人人爽AV片| 国产成人久久激情91| 亚洲国产日韩综合久久精品| 久久777国产线看观看精品| 久久久黄色大片| 国产精品久久久久久久久久免费| 免费精品久久天干天干| 国内精品久久久久久久coent| 国产激情久久久久久熟女老人| 91性高湖久久久久| 久久久久久久97| 国产成人精品综合久久久久| 国产三级精品久久| 国产一区二区精品久久| 久久99精品久久久久久久不卡| 午夜精品久久久内射近拍高清| 色成年激情久久综合| jizzjizz国产精品久久| 青青草原精品99久久精品66| 久久妇女高潮几次MBA| 色综合久久天天综线观看| 激情综合色综合久久综合| 国产成人AV综合久久| 国产女人aaa级久久久级| 久久香蕉综合色一综合色88| 国产91久久精品一区二区| 久久精品人人做人人妻人人玩| 久久九九久精品国产免费直播| 伊人久久大香线蕉精品不卡| 久久久久久久综合狠狠综合| 欧美黑人激情性久久| 亚洲国产美女精品久久久久∴| 久久青青草原亚洲av无码app| 欧美精品久久久久久久自慰| 久久久国产精品亚洲一区|