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

            woaidongmao

            文章均收錄自他人博客,但不喜標(biāo)題前加-[轉(zhuǎn)貼],因其丑陋,見諒!~
            隨筆 - 1469, 文章 - 0, 評(píng)論 - 661, 引用 - 0
            數(shù)據(jù)加載中……

            如何理解c和c ++的復(fù)雜類型聲明

            曾經(jīng)碰到過讓你迷惑不解、類似于int * (* (*fp1) (int) ) [10];這樣的變量聲明嗎?本文將由易到難,一步一步教會(huì)你如何理解這種復(fù)雜的C/C++聲明。

              我們將從每天都能碰到的較簡(jiǎn)單的聲明入手,然后逐步加入const修飾符和typedef,還有函數(shù)指針,最后介紹一個(gè)能夠讓你準(zhǔn)確地理解任何C/C++聲明的右左法則

              需要強(qiáng)調(diào)一下的是,復(fù)雜的C/C++聲明并不是好的編程風(fēng)格;我這里僅僅是教你如何去理解這些聲明。注意:為了保證能夠在同一行上顯示代碼和相關(guān)注釋,本文最好在至少1024x768分辨率的顯示器上閱讀。
            讓我們從一個(gè)非常簡(jiǎn)單的例子開始,如下:

            int n;



            這個(gè)應(yīng)該被理解為“declare n as an int”n是一個(gè)int型的變量)。接下去來看一下指針變量,如下:

            int *p;



            這個(gè)應(yīng)該被理解為“declare p as an int *”p是一個(gè)int *型的變量),或者說p是一個(gè)指向一個(gè)int型變量的指針。我想在這里展開討論一下:我覺得在聲明一個(gè)指針(或引用)類型的變量時(shí),最好將*(或&)寫在緊靠變量之前,而不是緊跟基本類型之后。這樣可以避免一些理解上的誤區(qū),比如:
            再來看一個(gè)指針的指針的例子:

            char **argv;



            理論上,對(duì)于指針的級(jí)數(shù)沒有限制,你可以定義一個(gè)浮點(diǎn)類型變量的指針的指針的指針的指針,再來看如下的聲明:

            int RollNum[30][4];

            int (*p)[4]=RollNum;

            int *q[5];

            這里,p被聲明為一個(gè)指向一個(gè)4元素(int類型)數(shù)組的指針,而q被聲明為一個(gè)包含5個(gè)元素(int類型的指針)的數(shù)組。另外,我們還可以在同一個(gè)聲明中混合實(shí)用*&,如下:

            int **p1;

            // p1 is a pointer  to a pointer  to an int.

            int *&p2;

            // p2 is a reference to a pointer  to an int.

            int &*p3;

            // ERROR: Pointer  to a reference is illegal.

            int &&p4;

            // ERROR: Reference to a reference is illegal.



            注:p1是一個(gè)int類型的指針的指針;p2是一個(gè)int類型的指針的引用;p3是一個(gè)int類型引用的指針(不合法!);p4是一個(gè)int類型引用的引用(不合法!)。

            const
            修飾符

            當(dāng)你想阻止一個(gè)變量被改變,可能會(huì)用到const關(guān)鍵字。在你給一個(gè)變量加上const修飾符的同時(shí),通常需要對(duì)它進(jìn)行初始化,因?yàn)橐院蟮娜魏螘r(shí)候你將沒有機(jī)會(huì)再去改變它。例如:

            const int n=5;

            int const m=10;



            上述兩個(gè)變量nm其實(shí)是同一種類型的——都是const int(整形恒量)。因?yàn)?span lang="EN-US">C++標(biāo)準(zhǔn)規(guī)定,const關(guān)鍵字放在類型或變量名之前等價(jià)的。我個(gè)人更喜歡第一種聲明方式,因?yàn)樗怀隽?span lang="EN-US">const修飾符的作用。當(dāng)const與指針一起使用時(shí),容易讓人感到迷惑。例如,我們來看一下下面的pq的聲明:

            const int *p;

            int const *q;



            他們當(dāng)中哪一個(gè)代表const int類型的指針(const直接修飾int),哪一個(gè)代表int類型的const指針(const直接修飾指針)?實(shí)際上,pq都被聲明為const int類型的指針。而int類型的const指針應(yīng)該這樣聲明: 

            int * const r= &n;

            // n has been declared as an int



            這里,pq都是指向const int類型的指針,也就是說,你在以后的程序里不能改變*p的值。而r是一個(gè)const指針,它在聲明的時(shí)候被初始化指向變量n(即r=&n;)之后,r的值將不再允許被改變(但*r的值可以改變)。

            組合上述兩種const修飾的情況,我們來聲明一個(gè)指向const int類型的const指針,如下:

            const int * const p=&n

            // n has been declared as const int



            下面給出的一些關(guān)于const的聲明,將幫助你徹底理清const的用法。不過請(qǐng)注意,下面的一些聲明是不能被編譯通過的,因?yàn)樗麄冃枰诼暶鞯耐瑫r(shí)進(jìn)行初始化。為了簡(jiǎn)潔起見,我忽略了初始化部分;因?yàn)榧尤氤跏蓟a的話,下面每個(gè)聲明都將增加兩行代碼。

            char ** p1;

            //    pointer to    pointer to    char

            const char **p2;

            //    pointer to    pointer to const char

            char * const * p3;

            //    pointer to const pointer to    char

            const char * const * p4;

            //    pointer to const pointer to const char

            char ** const p5;

            // const pointer to    pointer to    char

            const char ** const p6;

            // const pointer to    pointer to const char

            char * const * const p7;

            // const pointer to const pointer to    char

            const char * const * const p8;

            // const pointer to const pointer to const char



            注:p1是指向char類型的指針的指針;p2是指向const char類型的指針的指針;p3是指向char類型的const指針;p4是指向const char類型的const指針;p5是指向char類型的指針的const指針;p6是指向const char類型的指針的const指針;p7是指向char類型const指針的const指針;p8是指向const char類型的const指針的const指針。

            typedef
            的妙用

            typedef
            給你一種方式來克服“*只適合于變量而不適合于類型的弊端。你可以如下使用typedef

            typedef char * PCHAR;

            PCHAR p,q;



            這里的pq都被聲明為指針。(如果不使用typedefq將被聲明為一個(gè)char變量,這跟我們的第一眼感覺不太一致!)下面有一些使用typedef的聲明,并且給出了解釋:

            typedef char * a;

            // a is a pointer to a char

             

            typedef a b();

            // b is a function that returns

            // a pointer to a char

             

            typedef b *c;

            // c is a pointer to a function

            // that returns a pointer to a char

             

            typedef c d();

            // d is a function returning

            // a pointer to a function

            // that returns a pointer to a char

             

            typedef d *e;

            // e is a pointer to a function

            // returning a pointer to a

            // function that returns a

            // pointer to a char

             

            e var[10];

            // var is an array of 10 pointers to

            // functions returning pointers to

            // functions returning pointers to chars.



            typedef
            經(jīng)常用在一個(gè)結(jié)構(gòu)聲明之前,如下。這樣,當(dāng)創(chuàng)建結(jié)構(gòu)變量的時(shí)候,允許你不使用關(guān)鍵字struct(在C中,創(chuàng)建結(jié)構(gòu)變量時(shí)要求使用struct關(guān)鍵字,如struct tagPOINT a;而在C++中,struct可以忽略,如tagPOINT b)。

            typedef struct tagPOINT

            {

              int x;

              int y;

            }POINT;

             

            POINT p; /* Valid C code */

            函數(shù)指針

            函數(shù)指針可能是最容易引起理解上的困惑的聲明。函數(shù)指針在DOS時(shí)代寫TSR程序時(shí)用得最多;在Win32X-Windows時(shí)代,他們被用在需要回調(diào)函數(shù)的場(chǎng)合。當(dāng)然,還有其它很多地方需要用到函數(shù)指針:虛函數(shù)表,STL中的一些模板,Win NT/2K/XP系統(tǒng)服務(wù)等。讓我們來看一個(gè)函數(shù)指針的簡(jiǎn)單例子:




            int (*p)(char);



            這里p被聲明為一個(gè)函數(shù)指針,這個(gè)函數(shù)帶一個(gè)char類型的參數(shù),并且有一個(gè)int類型的返回值。另外,帶有兩個(gè)float類型參數(shù)、返回值是char類型的指針的指針的函數(shù)指針可以聲明如下:

            char ** (*p)(float, float);



            那么,帶兩個(gè)char類型的const指針參數(shù)、無返回值的函數(shù)指針又該如何聲明呢?參考如下:

            void * (*a[5])(char * const, char * const);



            右左法則是一個(gè)簡(jiǎn)單的法則,但能讓你準(zhǔn)確理解所有的聲明。這個(gè)法則運(yùn)用如下:從最內(nèi)部的括號(hào)開始閱讀聲明,向右看,然后向左看。當(dāng)你碰到一個(gè)括號(hào)時(shí)就調(diào)轉(zhuǎn)閱讀的方向。括號(hào)內(nèi)的所有內(nèi)容都分析完畢就跳出括號(hào)的范圍。這樣繼續(xù),直到整個(gè)聲明都被分析完畢。

            對(duì)上述右左法則做一個(gè)小小的修正:當(dāng)你第一次開始閱讀聲明的時(shí)候,你必須從變量名開始,而不是從最內(nèi)部的括號(hào)。

            下面結(jié)合例子來演示一下右左法則的使用。

            int * (* (*fp1) (int) ) [10];



            閱讀步驟:

            1.
            從變量名開始——fp1

            2.
            往右看,什么也沒有,碰到了),因此往左看,碰到一個(gè)*——一個(gè)指針

            3.
            跳出括號(hào),碰到了(int)——一個(gè)帶一個(gè)int參數(shù)的函數(shù)

            4.
            向左看,發(fā)現(xiàn)一個(gè)*——(函數(shù))返回一個(gè)指針

            5.
            跳出括號(hào),向右看,碰到[10]——一個(gè)10元素的數(shù)組

            6.
            向左看,發(fā)現(xiàn)一個(gè)*——指針

            7.
            向左看,發(fā)現(xiàn)int——int類型

            總結(jié):fp1被聲明成為一個(gè)函數(shù)的指針,該函數(shù)返回指向指針數(shù)組的指針.

            再來看一個(gè)例子:

            int *( *( *arr[5])())();



            閱讀步驟:

            1.
            從變量名開始——arr

            2.
            往右看,發(fā)現(xiàn)是一個(gè)數(shù)組——一個(gè)5元素的數(shù)組

            3.
            向左看,發(fā)現(xiàn)一個(gè)*——指針

            4.
            跳出括號(hào),向右看,發(fā)現(xiàn)()——不帶參數(shù)的函數(shù)

            5.
            向左看,碰到*——(函數(shù))返回一個(gè)指針

            6.
            跳出括號(hào),向右發(fā)現(xiàn)()——不帶參數(shù)的函數(shù)

            7.
            向左,發(fā)現(xiàn)*——(函數(shù))返回一個(gè)指針

            8.
            繼續(xù)向左,發(fā)現(xiàn)int——int類型

            還有更多的例子:

            float ( * ( *b()) [] )();

            // b is a function that returns a

            // pointer to an array of pointers

            // to functions returning floats.

            void * ( *c) ( char, int (*)());

            // c is a pointer to a function that takes

            // two parameters:

            // a char and a pointer to a

            // function that takes no

            // parameters and returns

            // an int

            // and returns a pointer to void.

            void ** (*d) (int &,

            char **(*)(char *, char **));

            // d is a pointer to a function that takes

            // two parameters:

            // a reference to an int and a pointer

            // to a function that takes two parameters:

            // a pointer to a char and a pointer

            // to a pointer to a char

            // and returns a pointer to a pointer

            // to a char

            // and returns a pointer to a pointer to void

            float ( * ( * e[10])

              (int &) ) [5];

            // e is an array of 10 pointers to

            // functions that take a single

            // reference to an int as an argument

            // and return pointers to

            // an array of 5 floats.

             

            posted on 2008-11-07 22:45 肥仔 閱讀(462) 評(píng)論(0)  編輯 收藏 引用 所屬分類: C++ 基礎(chǔ)

            91麻精品国产91久久久久| 99久久免费只有精品国产| 欧美亚洲国产精品久久久久| 久久伊人精品青青草原日本| 伊人色综合久久天天人守人婷| 99久久国产亚洲综合精品| 久久夜色精品国产噜噜亚洲AV| 99久久国语露脸精品国产| 99久久精品免费看国产一区二区三区| 久久精品二区| 久久精品aⅴ无码中文字字幕不卡| 精品久久久久久中文字幕| 久久99精品久久久久久噜噜 | 久久国产成人精品麻豆| 久久精品视频91| 精品久久久久久中文字幕| 精品久久久久成人码免费动漫| 国产一区二区精品久久| 狠狠色狠狠色综合久久| 久久久WWW成人免费精品| 国内精品久久久久伊人av| 久久久久免费精品国产| 久久久久国产| 国产香蕉97碰碰久久人人| 亚洲国产精品无码久久久秋霞2| 久久精品国产欧美日韩| 99久久国产免费福利| AAA级久久久精品无码片| 久久久久亚洲Av无码专| 狠狠色丁香久久婷婷综合| 久久乐国产综合亚洲精品| 久久精品亚洲精品国产欧美| 久久久久夜夜夜精品国产| 国产精品一区二区久久| 国产欧美久久久精品| 精品久久久久久中文字幕人妻最新 | 狠狠精品久久久无码中文字幕| 亚洲国产成人久久综合一区77 | 欧洲成人午夜精品无码区久久| 久久精品一本到99热免费| 久久这里都是精品|