青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

posts - 18, comments - 7, trackbacks - 0, articles - 0
  C++博客 :: 首頁(yè) :: 新隨筆 :: 聯(lián)系 :: 聚合  :: 管理
       
        右左法則是一個(gè)既著名又常用的方法。不過(guò),右左法則其實(shí)并不是C標(biāo)準(zhǔn)里面的內(nèi)容,它是從C標(biāo)準(zhǔn)的聲明規(guī)定中歸納出來(lái)的方法。C標(biāo)準(zhǔn)的聲明規(guī)則,是用來(lái)解決如何創(chuàng)建聲明的,而右左法則是用來(lái)解決如何辯識(shí)一個(gè)聲明的,兩者可以說(shuō)是相反的。右左法則的英文原文是這樣說(shuō)的:

The right-left rule: Start reading the declaration from the innermost parentheses, go right, and then go left. When you encounter parentheses, the direction should be reversed. Once everything in the parentheses has been parsed, jump out of it. Continue till the whole declaration has been parsed.


這段英文的翻譯如下:

右左法則:首先從最里面的圓括號(hào)看起,然后往右看,再往左看。每當(dāng)遇到圓括號(hào)時(shí),就應(yīng)該掉轉(zhuǎn)閱讀方向。一旦解析完圓括號(hào)里面所有的東西,就跳出圓括號(hào)。重復(fù)這個(gè)過(guò)程直到整個(gè)聲明解析完畢。

        筆者要對(duì)這個(gè)法則進(jìn)行一個(gè)小小的修正,應(yīng)該是從未定義的標(biāo)識(shí)符開(kāi)始閱讀,而不是從括號(hào)讀起,之所以是未定義的標(biāo)識(shí)符,是因?yàn)橐粋€(gè)聲明里面可能有多個(gè)標(biāo)識(shí)符,但未定義的標(biāo)識(shí)符只會(huì)有一個(gè)。

        現(xiàn)在通過(guò)一些例子來(lái)討論右左法則的應(yīng)用,先從最簡(jiǎn)單的開(kāi)始,逐步加深:

int (*func)(int *p);

首先找到那個(gè)未定義的標(biāo)識(shí)符,就是func,它的外面有一對(duì)圓括號(hào),而且左邊是一個(gè)*號(hào),這說(shuō)明func是一個(gè)指針,然后跳出這個(gè)圓括號(hào),先看右邊,也是一個(gè)圓括號(hào),這說(shuō)明(*func)是一個(gè)函數(shù),而func是一個(gè)指向這類(lèi)函數(shù)的指針,就是一個(gè)函數(shù)指針,這類(lèi)函數(shù)具有int*類(lèi)型的形參,返回值類(lèi)型是int。

int (*func)(int *p, int (*f)(int*));

func被一對(duì)括號(hào)包含,且左邊有一個(gè)*號(hào),說(shuō)明func是一個(gè)指針,跳出括號(hào),右邊也有個(gè)括號(hào),那么func是一個(gè)指向函數(shù)的指針,這類(lèi)函數(shù)具有int *和int (*)(int*)這樣的形參,返回值為int類(lèi)型。再來(lái)看一看func的形參int (*f)(int*),類(lèi)似前面的解釋?zhuān)琭也是一個(gè)函數(shù)指針,指向的函數(shù)具有int*類(lèi)型的形參,返回值為int。

int (*func[5])(int *p);

func右邊是一個(gè)[]運(yùn)算符,說(shuō)明func是一個(gè)具有5個(gè)元素的數(shù)組,func的左邊有一個(gè)*,說(shuō)明func的元素是指針,要注意這里的*不是修飾func的,而是修飾func[5]的,原因是[]運(yùn)算符優(yōu)先級(jí)比*高,func先跟[]結(jié)合,因此*修飾的是func[5]。跳出這個(gè)括號(hào),看右邊,也是一對(duì)圓括號(hào),說(shuō)明func數(shù)組的元素是函數(shù)類(lèi)型的指針,它所指向的函數(shù)具有int*類(lèi)型的形參,返回值類(lèi)型為int。


int (*(*func)[5])(int *p);

func被一個(gè)圓括號(hào)包含,左邊又有一個(gè)*,那么func是一個(gè)指針,跳出括號(hào),右邊是一個(gè)[]運(yùn)算符號(hào),說(shuō)明func是一個(gè)指向數(shù)組的指針,現(xiàn)在往左看,左邊有一個(gè)*號(hào),說(shuō)明這個(gè)數(shù)組的元素是指針,再跳出括號(hào),右邊又有一個(gè)括號(hào),說(shuō)明這個(gè)數(shù)組的元素是指向函數(shù)的指針。總結(jié)一下,就是:func是一個(gè)指向數(shù)組的指針,這個(gè)數(shù)組的元素是函數(shù)指針,這些指針指向具有int*形參,返回值為int類(lèi)型的函數(shù)。

int (*(*func)(int *p))[5];

func是一個(gè)函數(shù)指針,這類(lèi)函數(shù)具有int*類(lèi)型的形參,返回值是指向數(shù)組的指針,所指向的數(shù)組的元素是具有5個(gè)int元素的數(shù)組。

要注意有些復(fù)雜指針聲明是非法的,例如:

int func(void) [5];

func是一個(gè)返回值為具有5個(gè)int元素的數(shù)組的函數(shù)。但C語(yǔ)言的函數(shù)返回值不能為數(shù)組,這是因?yàn)槿绻试S函數(shù)返回值為數(shù)組,那么接收這個(gè)數(shù)組的內(nèi)容的東西,也必須是一個(gè)數(shù)組,但C語(yǔ)言的數(shù)組名是一個(gè)右值,它不能作為左值來(lái)接收另一個(gè)數(shù)組,因此函數(shù)返回值不能為數(shù)組。

int func[5](void);

func是一個(gè)具有5個(gè)元素的數(shù)組,這個(gè)數(shù)組的元素都是函數(shù)。這也是非法的,因?yàn)閿?shù)組的元素除了類(lèi)型必須一樣外,每個(gè)元素所占用的內(nèi)存空間也必須相同,顯然函數(shù)是無(wú)法達(dá)到這個(gè)要求的,即使函數(shù)的類(lèi)型一樣,但函數(shù)所占用的空間通常是不相同的。

        作為練習(xí),下面列幾個(gè)復(fù)雜指針聲明給讀者自己來(lái)解析,答案放在第十章里。

int (*(*func)[5][6])[7][8];

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

int (*(*func[7][8][9])(int*))[5];

        實(shí)際當(dāng)中,需要聲明一個(gè)復(fù)雜指針時(shí),如果把整個(gè)聲明寫(xiě)成上面所示的形式,對(duì)程序可讀性是一大損害。應(yīng)該用typedef來(lái)對(duì)聲明逐層分解,增強(qiáng)可讀性,例如對(duì)于聲明:

int (*(*func)(int *p))[5];

可以這樣分解:

typedef  int (*PARA)[5];
typedef PARA (*func)(int *);

這樣就容易看得多了。

const一詞是英文constant的縮寫(xiě),設(shè)立這個(gè)關(guān)鍵字的本意,是希望讓它所修飾的對(duì)象成為一個(gè)常量。記得在國(guó)家間的外交中,有一個(gè)經(jīng)常用到的術(shù)語(yǔ):“從事與身份不符的活動(dòng)”,這個(gè)const恰恰也正從事著這樣的活動(dòng),呵呵。C語(yǔ)言可以有三種方法定義一個(gè)常量:#define、const和枚舉,但只有枚舉才是真正的常量,什么是真正的常量?真正的常量是沒(méi)有存儲(chǔ)空間的,是一個(gè)右值,這意味著通過(guò)任何合法的手段也不會(huì)被修改,但被const修飾的對(duì)象依然是一個(gè)左值,盡管這個(gè)對(duì)象被const限定,筆者仍然至少可以找到三種合法的手段去修改它,而#define所做的只不過(guò)是編譯期替換而已,只有枚舉常量才能真正做到這一點(diǎn)。const實(shí)在不應(yīng)該被命名為const,這會(huì)讓人們產(chǎn)生誤解,它應(yīng)該命名為readonly或類(lèi)似的字眼,意即不能通過(guò)被const修飾的對(duì)象修改它所指向的對(duì)象或者它所代表的對(duì)象。但在C的世界里把const稱(chēng)為常量早已是普遍的現(xiàn)象,那我們就只好隨大流咯,也稱(chēng)之為常量吧,只要知道它實(shí)際上不是真正的常量就行了。

        第七章曾經(jīng)討論過(guò)const int *p;與int * const p的區(qū)別,這兩個(gè)聲明的中文名稱(chēng)常常搞得混亂不堪。第一個(gè)聲明的const是聲明說(shuō)明符,它修飾p所指向的對(duì)象,但p仍然是可變的,這意味著p是一個(gè)指向常量的指針,簡(jiǎn)稱(chēng)常量指針。第二個(gè)聲明的const是聲明符的一部分,它修飾的對(duì)象是p,這意味著p是一個(gè)常量,而且是一個(gè)指針類(lèi)型的常量,簡(jiǎn)稱(chēng)指針常量。指針常量又常常被人稱(chēng)為“常指針”或“常指針變量”,常指針變量這個(gè)名稱(chēng)有點(diǎn)蹩腳,又常又變的,容易讓人摸不著頭腦,最好還是不要這樣稱(chēng)呼。這里還得再?gòu)?qiáng)調(diào)一次指針常量與地址常量是不同的,不能把數(shù)組名稱(chēng)為指針常量,也不能把指針常量稱(chēng)為地址常量,因?yàn)橹羔槼A恳廊皇且粋€(gè)左值,而數(shù)組名是一個(gè)右值,這里肯定有人會(huì)問(wèn):“什么?指針常量是一個(gè)左值?我沒(méi)聽(tīng)錯(cuò)吧?”你的確沒(méi)有聽(tīng)錯(cuò),C89對(duì)于左值是這樣定義的:

對(duì)象是一個(gè)命名的存儲(chǔ)區(qū)域,左值(lvalue)是引用某個(gè)對(duì)象的表達(dá)式。

換言之,如果一個(gè)表達(dá)式引用的是一個(gè)具有具體存儲(chǔ)空間的對(duì)象,它就是一個(gè)左值!那么既然指針常量是一個(gè)左值,為什么卻不能給它賦值呢?是因?yàn)樗芟抻谫x值表達(dá)式的一條規(guī)則:賦值表達(dá)式的左值不能含有限定詞!

        為了防止指針指向的常量被修改,C標(biāo)準(zhǔn)對(duì)于指針間賦值有一個(gè)規(guī)定,就是左值必須包含右值的所有限定詞。 這就限定了一個(gè)指向const對(duì)象的指針不能賦值給指向非const對(duì)象的指針,但反過(guò)來(lái)就允許。這個(gè)規(guī)定初看上去非常合理,但其效用其實(shí)只限于一級(jí)指針,二級(jí)指針間的賦值即使?jié)M足規(guī)定也不再安全,下面舉個(gè)例子:

const int i=10;
const int **p1;
int *p2;
p1 = &p2;
*p1 = &i;
*p2 = 20;

現(xiàn)在你會(huì)發(fā)現(xiàn),作為常量的i的值被修改了。i的值被修改的關(guān)鍵原因在*p1=&i;這一句,&i是一個(gè)指向常量的一級(jí)地址,如果沒(méi)有二級(jí)指針p1,受限于上述規(guī)定,作為左值接受這個(gè)一級(jí)地址的指針就必須也是一個(gè)指向常量的一級(jí)指針,于是就不能進(jìn)行下一步賦值20的操作。因此,正由于指向const對(duì)象的二級(jí)指針p1的出現(xiàn),使得*p1也是一個(gè)指向const的指針,于是*p1=&i能夠合法地運(yùn)行,常量i的值被修改也就成了一個(gè)預(yù)想中的結(jié)果了。有鑒于此,某些編譯器也會(huì)限定非const二級(jí)指針之間的賦值,規(guī)定上面的p1=&p2也是非法的。

        第七章介紹聲明符的指針部分有一種形式:

* 類(lèi)型限定符表opt 指針

這種形式產(chǎn)生了一種比較復(fù)雜的帶const的指針,例如:

const int * const *** const ** const p;

這是一個(gè)會(huì)讓人頭暈?zāi)垦5谋磉_(dá)式,聲明符部分嵌套了九次,如何辨認(rèn)誰(shuí)是const,誰(shuí)不是const呢?一旦明白了其中的原則,其實(shí)是非常簡(jiǎn)單的。第一和最后一個(gè)const大家都已經(jīng)很熟悉的了。對(duì)于藏在一堆*號(hào)中的const,有一個(gè)非常簡(jiǎn)單的原則:const與左邊最后一個(gè)聲明說(shuō)明符之間有多少個(gè)*號(hào),那么就是多少級(jí)指針是const的。例如從右數(shù)起第二個(gè)const,它與int之間有4個(gè)*號(hào),那么p的四級(jí)部分就是const的,下面的賦值表達(dá)式是非法的:

**p = (int *const***)10;
但下面的賦值是允許的:
***p=(int*const**)10;
從左邊數(shù)起第二個(gè)const,它與int之間有1個(gè)*,那么p的一級(jí)部分是const的,也就是*****p = (int*const***const*)10;是非法的。

對(duì)于一個(gè)函數(shù):

void func(void);

我們通常可以定義一個(gè)這樣的函數(shù)指針指向它:

void (*p)(void) = func;

通過(guò)p調(diào)用func時(shí),通常有兩種寫(xiě)法:

p();或者(*p)();

 圍繞這兩種寫(xiě)法,當(dāng)初C89制定的時(shí)候曾經(jīng)有過(guò)爭(zhēng)論。(*p)();是一種舊式的規(guī)定,舊式規(guī)定圓括號(hào)左邊必須具有“函數(shù)”類(lèi)型,如果是指向函數(shù)的指針,那么必須加上*聲明符。但C89不再把圓括號(hào)的左邊限定為“函數(shù)”類(lèi)型,而是一個(gè)后綴表達(dá)式。那么問(wèn)題就來(lái)了,如果p的值是函數(shù)地址,那么*號(hào)就是聲明符,但如果p指向的內(nèi)容是函數(shù)地址,*號(hào)就得被看作運(yùn)算符了。同一種形式會(huì)有兩種解釋?zhuān)@是一個(gè)矛盾。不僅函數(shù)調(diào)用如此,指向數(shù)組的指針也存在這種矛盾。編譯器為了處理這種情況得增加代碼,效率自然就降低了。爭(zhēng)論的最后結(jié)果是誰(shuí)也不能把對(duì)方完全說(shuō)服,于是就干脆兩種都支持了。筆者認(rèn)為應(yīng)該拋棄舊式的規(guī)定,p();這種形式簡(jiǎn)潔明了,又符合函數(shù)的一般形式,何樂(lè)而不為?


        第八章練習(xí)的答案,同時(shí)給出用typedef的分解方法:


int (*(*func)[5][6])[7][8];

func是一個(gè)指向數(shù)組的指針,這類(lèi)數(shù)組的元素是一個(gè)具有5X6個(gè)int元素的二維數(shù)組,而這個(gè)二維數(shù)組的元素又是一個(gè)二維數(shù)組。

typedef int (*PARA)[7][8];
typedef PARA (*func)[5][6];


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

func是一個(gè)函數(shù)指針,這類(lèi)函數(shù)的返回值是一個(gè)指向數(shù)組的指針,所指向數(shù)組的元素也是函數(shù)指針,指向的函數(shù)具有int*形參,返回值為int。

typedef int (*PARA1)(int*);
typedef PARA1 (*PARA2)[5];
typedef PARA2 (*func)(int*);

int (*(*func[7][8][9])(int*))[5];

func是一個(gè)數(shù)組,這個(gè)數(shù)組的元素是函數(shù)指針,這類(lèi)函數(shù)具有int*的形參,返回值是指向數(shù)組的指針,所指向的數(shù)組的元素是具有5個(gè)int元素的數(shù)組。

typedef int (*PARA1)[5];
typedef PARA1 (*PARA2)(int*);
typedef PARA2 func[7][8][9];

 原文地址 http://blog.csdn.net/megaboy/archive/2005/09/17/482783.aspx

Feedback

# re: 指針右左法則----復(fù)雜指針解析[未登錄](méi)  回復(fù)  更多評(píng)論   

2008-09-17 13:07 by 陳梓瀚(vczh)
其實(shí)如果寫(xiě)得出(其實(shí)不難)指針和數(shù)組的聲明的EBNF的話,那么直接看就可以反應(yīng)過(guò)來(lái)了……

# re: 指針右左法則----復(fù)雜指針解析  回復(fù)  更多評(píng)論   

2008-12-01 22:15 by 鹿亮
您對(duì)編譯原理相當(dāng)熟悉啊

# re: 指針右左法則----復(fù)雜指針解析  回復(fù)  更多評(píng)論   

2009-04-03 12:49 by insulted
非常之不錯(cuò)!

只有注冊(cè)用戶登錄后才能發(fā)表評(píng)論。
網(wǎng)站導(dǎo)航: 博客園   IT新聞   BlogJava   博問(wèn)   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            欧美激情精品久久久久久变态| 亚洲国产综合在线| 亚洲高清在线视频| 国产一区二区三区久久久久久久久| 亚洲成人在线免费| 久久一区二区精品| 国产精品九九| 亚洲精品中文在线| 亚洲另类春色国产| 男人的天堂亚洲| 美腿丝袜亚洲色图| 韩日精品视频| 久久狠狠亚洲综合| 久久久国产精品亚洲一区| 国产精品日韩精品欧美精品| 亚洲九九精品| 一区二区三区色| 欧美日本韩国一区| 亚洲免费av电影| 亚洲午夜久久久久久尤物| 欧美激情视频一区二区三区免费| 欧美激情第1页| 亚洲欧洲精品一区| 欧美成人精品在线视频| 亚洲黄色影院| 一区二区三区四区五区在线| 欧美日韩高清在线一区| 亚洲欧洲日韩女同| 一区二区三区www| 国产精品wwwwww| 亚洲欧美不卡| 久久久激情视频| 亚洲国产欧美一区二区三区同亚洲| 久久露脸国产精品| 欧美激情视频一区二区三区在线播放 | 欧美日韩在线视频一区| 一区二区三区视频在线播放| 亚洲一区久久久| 国产欧美一区二区精品忘忧草| 午夜视频精品| 免费成人黄色| 洋洋av久久久久久久一区| 欧美日韩免费看| 亚洲欧美中文日韩在线| 麻豆av一区二区三区| 亚洲国产一区二区视频| 欧美日本视频在线| 亚洲男人的天堂在线观看| 另类人畜视频在线| 日韩亚洲欧美成人| 国产欧美 在线欧美| 久热精品在线视频| 日韩一区二区精品视频| 久久国产精品久久w女人spa| 在线日韩电影| 欧美午夜在线一二页| 久久国内精品视频| 亚洲日产国产精品| 久久久.com| 一本色道久久| 国产一区清纯| 欧美日韩午夜精品| 久久久国产精品一区二区中文| 亚洲人成在线观看网站高清| 欧美一进一出视频| 亚洲乱码国产乱码精品精天堂| 国产精品福利在线观看网址| 久久夜色精品国产欧美乱极品| 在线亚洲高清视频| 欧美成人免费一级人片100| 亚洲综合第一| 亚洲人成高清| 国产一区二区三区直播精品电影| 欧美激情一区二区| 久久www成人_看片免费不卡| 亚洲免费电影在线观看| 免费久久99精品国产自在现线| 久久日韩精品| 日韩视频在线免费| 久久三级视频| 亚洲一二三区在线| 亚洲黄色成人久久久| 久久黄色影院| 亚洲一区久久久| 日韩亚洲不卡在线| 91久久国产综合久久| 国产夜色精品一区二区av| 欧美视频在线观看视频极品| 欧美xxx成人| 老司机亚洲精品| 久久久精品国产一区二区三区| 亚洲一区二区视频| 99精品视频一区| 亚洲精品乱码| 亚洲国产婷婷综合在线精品| 老司机精品视频网站| 久久国产主播| 久久狠狠久久综合桃花| 欧美一区二区精品久久911| 亚洲视频播放| 亚洲在线播放| 亚洲欧美在线x视频| 中国女人久久久| 中文亚洲免费| 亚洲性线免费观看视频成熟| aa级大片欧美| 亚洲视频在线免费观看| 一区二区三区欧美在线| 99亚洲视频| 这里只有精品电影| 亚洲专区在线| 午夜在线精品| 久久久青草青青国产亚洲免观| 久久精品女人| 久久人人97超碰精品888| 毛片av中文字幕一区二区| 免费成人av在线看| 亚洲国产中文字幕在线观看| 日韩视频在线观看一区二区| 中文日韩在线视频| 性色av香蕉一区二区| 久久九九电影| 欧美sm视频| 国产精品ⅴa在线观看h| 国产精品普通话对白| 国产一区二区黄色| 亚洲国产小视频在线观看| 9国产精品视频| 欧美亚洲网站| 免费不卡在线观看| 日韩视频在线一区二区| 午夜日韩在线观看| 免费观看成人| 国产精品高潮呻吟久久| 精品91在线| 一区二区三区欧美视频| 久久福利资源站| 欧美激情在线狂野欧美精品| 亚洲最新色图| 久久人人爽爽爽人久久久| 欧美日韩国产a| 国产午夜久久久久| 日韩午夜av在线| 久久精品国产清自在天天线| 亚洲第一精品影视| 亚洲欧美在线一区二区| 欧美www视频| 国产欧美日韩在线视频| 亚洲日本中文字幕| 欧美专区福利在线| 91久久午夜| 久久视频国产精品免费视频在线| 欧美午夜精品久久久| 一区二区三区亚洲| 午夜精彩视频在线观看不卡| 亚洲国产成人精品视频| 午夜在线一区| 欧美午夜不卡| 亚洲人成在线免费观看| 久久国产主播精品| av成人激情| 欧美精品国产精品| 136国产福利精品导航| 欧美亚洲日本网站| 99视频精品全部免费在线| 免费在线看一区| 国产亚洲一区在线播放| 亚洲欧美日韩国产| 亚洲日本视频| 免费观看一区| 韩日欧美一区| 久久久久国产精品一区二区| 一区二区三区免费在线观看| 欧美va天堂| 亚洲国产精品日韩| 免费视频亚洲| 久久米奇亚洲| 国产主播一区二区三区| 欧美一区午夜精品| 亚洲视频免费看| 国产精品扒开腿做爽爽爽视频| 亚洲日本欧美天堂| 亚洲国产精品va在线观看黑人 | 欧美国产精品va在线观看| 国产一区99| 久久精品国产亚洲aⅴ| 亚洲一区二区三区激情| 国产精品乱码一区二区三区| 在线亚洲欧美视频| 99在线视频精品| 欧美日韩亚洲不卡| 亚洲一区二区精品视频| 99热精品在线| 欧美日韩国产综合视频在线观看| 亚洲美女少妇无套啪啪呻吟| 亚洲高清资源综合久久精品| 欧美.日韩.国产.一区.二区| 亚洲激情欧美激情| 亚洲日本欧美| 国产精品久久久久久久电影|