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

            歲月流轉(zhuǎn),往昔空明

            C++博客 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
              118 Posts :: 3 Stories :: 413 Comments :: 0 Trackbacks
            在進(jìn)行靜態(tài)強(qiáng)類(lèi)型語(yǔ)言的設(shè)計(jì)過(guò)程中,是一定需要提供一種語(yǔ)法實(shí)現(xiàn)變量和類(lèi)型的關(guān)聯(lián)。這種語(yǔ)法一般稱(chēng)之為 “聲明” 或者 “定義”。

            如果用一種人類(lèi)易讀的方式進(jìn)行表達(dá),可以寫(xiě)作 define variable_name as type_name。沒(méi)有錯(cuò),你看到的這種形式類(lèi)似于VB當(dāng)中 Dim As的方法。在語(yǔ)法分析的過(guò)程中,這種方法的好處很明顯。define 作為提示字,意味著一個(gè)聲明或者定義的開(kāi)始,as 則代表后續(xù)的Tokens都是用于一個(gè)類(lèi)型的,這樣關(guān)鍵字可以很顯著的將語(yǔ)義區(qū)分開(kāi)。

            但是這種寫(xiě)法并不方便。C 一類(lèi)的語(yǔ)言,都選用一種 prefix declaration specifier 的方式,也就是我們常常見(jiàn)到的:type_name variable_name 這樣的形式。舉個(gè)最簡(jiǎn)單的例子,int i;。如果有類(lèi)型修飾,可以作為一個(gè)基本類(lèi)型的前綴或者后綴出現(xiàn)。例如const int i; 或者 int const i; 至于修飾含義是左綁定還是右綁定,這個(gè)需要取決于語(yǔ)言本身的設(shè)計(jì)。

            如果事情是這個(gè)樣子的話(huà),也就沒(méi)什么好說(shuō)的了。但是在C語(yǔ)言里面,有兩個(gè)例外:函數(shù)和數(shù)組。例如,在C里面定義一個(gè)數(shù)組,寫(xiě)作:const int array[expr]; 這種寫(xiě)法既不是前綴寫(xiě)法,也不是后綴寫(xiě)法。類(lèi)型被變量?jī)煞至恕H绻麅H僅是一個(gè)數(shù)組定義,那也好辦,當(dāng)做特殊情況處理就好了。
            但是有時(shí)候我們的數(shù)組元素會(huì)變得非常復(fù)雜。 舉個(gè)例子,( struct {...} const [ constant ] identifier ( params... )  ) [ expr ]。你能理解這樣一個(gè)復(fù)雜的定義其實(shí)是一個(gè)函數(shù)的數(shù)組么?不僅僅是你不能,我想在撰寫(xiě)語(yǔ)法規(guī)則的時(shí)候,又困難,又不合邏輯。

            在C的EBNF中,這個(gè)問(wèn)題解決起來(lái)也很復(fù)雜。
            在這里,我們簡(jiǎn)化一下C的語(yǔ)法,不考慮C的指針,不考慮變量初始化,不考慮類(lèi)型修飾符,也不考慮一個(gè)類(lèi)型定義多個(gè)變量的情況。
            這就意味著你只能寫(xiě) int i; int j; j = 0; 而不能寫(xiě) int i, j = 0;

            declaration ::= declaration_specifier declarator

            declarator ::= identifier
                           | delcarator '['  expr ']'
                           | declarator '(' parameters_declaration_list ')'
                           | '(' declarator ')'


            那么我問(wèn)你,declarator是個(gè)什么東西。變量名?不是。函數(shù)聲明?也不是。數(shù)組?也不是。declaration_specifier呢?變量類(lèi)型?是。數(shù)組元素類(lèi)型?是。函數(shù)返回值類(lèi)型?也是。顯然這樣一個(gè)語(yǔ)法要素具備了太多的語(yǔ)義。更重要的是,沒(méi)到最后,你是沒(méi)法確定declaration_specifier究竟是一個(gè)什么含義,identifier所代表的,究竟是個(gè)什么東西。顯然只有在聲明匹配完成之后,還需要進(jìn)行復(fù)雜的推導(dǎo)過(guò)程,才能確定變量的嵌套結(jié)構(gòu)。

            這個(gè)問(wèn)題還導(dǎo)致了C語(yǔ)言里面的這么一個(gè)特性:那就是很出名的指針?lè)?hào)*的變量綁定性質(zhì)。在C語(yǔ)言中,*,[],() 操作符并沒(méi)有理解為對(duì)類(lèi)型的修飾,而是理解為對(duì)變量的修飾。這就讓我們必須要這么寫(xiě): int m[expr], n[expr]; int m( int, int ), n( int, float );
            而對(duì)變量,寫(xiě)法就成了: int x, y; 這導(dǎo)致了同樣的寫(xiě)法兩者在語(yǔ)義上的不一致性。這也是為什么新手云里霧里的根本原因了。按照普通變量的規(guī)矩,函數(shù)應(yīng)該寫(xiě)成 int (x, y) (int);這樣的結(jié)構(gòu)。好吧,這樣還挑戰(zhàn)不倒你。但是如果我更復(fù)雜一點(diǎn),加上初始化呢?就變成了 int ( x = p0, y ) (int) 這樣的結(jié)構(gòu),呃。

            為什么C會(huì)這么做?難道完全的前置類(lèi)型會(huì)讓語(yǔ)法分析工作變難么?很顯然不會(huì)。雖然C語(yǔ)言如此聲明的出發(fā)點(diǎn)不可考,但是想讓普通類(lèi)型和數(shù)組聲明維持同樣的語(yǔ)法結(jié)構(gòu)是很簡(jiǎn)單的事情,C#就給了一個(gè)很好的答案。在C#中,變量是如此聲明的:

            declaration ::= declaration_specifier declarator
            declaration_specifier ::= function_specifier | array_specifier | identifier
                                      | '(' declaration_specifier ')'
            function_specifier ::= declaration_specifier '(' parameter_declaration_list ')'
            array_specifier ::= declaration_specifier '[' expression_list ']'


            這樣,declaration_specifier完全就變成了類(lèi)型,而declarator部分就和類(lèi)型脫鉤了。在這種聲明方式中,我們就這么定義一個(gè)變量 int [] x, y, z; OK,這樣大家就理解了,x,y,z都是一個(gè)數(shù)組。而不會(huì)造成C語(yǔ)言當(dāng)中的誤解。

            最后討論一下類(lèi)型修飾的問(wèn)題。這里只討論單一類(lèi)型的類(lèi)型修飾,下面我們會(huì)看到,復(fù)合類(lèi)型其實(shí)也是一樣的。我們將類(lèi)型聲明和表達(dá)式進(jìn)行類(lèi)比,就可以將類(lèi)型理解為變量,類(lèi)型修飾理解為單目操作符。

            const type  <==類(lèi)比==>  ~var

            const就相當(dāng)于按位取反操作符~,type就相當(dāng)于var。const type這個(gè)表達(dá)式的結(jié)果就是一個(gè)常量化的type。那么,我們可以更廣泛的將聲明理解成 type_expression variable_name 這樣的形式。type_expression在語(yǔ)義分析的時(shí)候進(jìn)行類(lèi)型演算得出結(jié)果,variable_name則利用類(lèi)型表達(dá)式獲得真正的類(lèi)型,并實(shí)例化。下面我們寫(xiě)出type_expression的演算語(yǔ)法:

            type_expression ::= type_identifier
                                | type_op type_expression  /* prefix  style */
                                | type_expression type_op  /* postfix style */
            type_op ::= type_qualifier

            當(dāng)然,對(duì)于 const int volatile 這樣的聲明,這個(gè)表達(dá)式還有二義性。這個(gè)二義性可以通過(guò)一定的方法消除,這一點(diǎn)一般的編譯原理教材都有詳細(xì)的討論。并且,我們完全可以將()和[]也納入到type_operator中,這兩個(gè)操作一個(gè)可以構(gòu)造出函數(shù)類(lèi)型,一個(gè)構(gòu)造出數(shù)組類(lèi)型來(lái),這樣類(lèi)型問(wèn)題就得到了一個(gè)遞歸一致的解決。

            當(dāng)然,更重要的是,我將type_expression variable_name這樣的聲明式變成typedef type_expression variable_name呢?

            哈哈。

            最后嚴(yán)重感謝一下VCZH,因?yàn)檫@小子吃了足夠的shit,我就可以不用繼續(xù)吃shit了。正所謂前人栽樹(shù)后人乘涼。

            posted on 2009-02-25 01:33 空明流轉(zhuǎn) 閱讀(1978) 評(píng)論(2)  編輯 收藏 引用

            評(píng)論

            # re: 靜態(tài)強(qiáng)類(lèi)型語(yǔ)言的類(lèi)型聲明與變量聲明 2009-02-25 01:43 陳梓瀚(vczh)
            囧  回復(fù)  更多評(píng)論
              

            # re: 靜態(tài)強(qiáng)類(lèi)型語(yǔ)言的類(lèi)型聲明與變量聲明[未登錄](méi) 2009-02-27 09:37 六水
            哈哈,這句說(shuō)的太經(jīng)典了  回復(fù)  更多評(píng)論
              


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


            亚洲人成精品久久久久| 午夜精品久久久久久影视777| 性高湖久久久久久久久AAAAA| 亚洲一区中文字幕久久 | 精品久久久久久99人妻| 久久久久黑人强伦姧人妻| 亚洲乱码中文字幕久久孕妇黑人| 久久精品国产精品亚洲毛片| 99久久国产综合精品五月天喷水| 久久久久国产精品三级网| 无码人妻久久一区二区三区蜜桃| 亚洲精品乱码久久久久久自慰| 国产综合久久久久| 无码国内精品久久综合88| 人妻精品久久久久中文字幕69 | 久久久久亚洲AV成人片| 99久久久精品免费观看国产| 久久久免费观成人影院| 久久精品免费大片国产大片| 亚洲综合熟女久久久30p| 日韩人妻无码一区二区三区久久99| 国内精品久久人妻互换| 无码八A片人妻少妇久久| 久久福利片| 99久久精品无码一区二区毛片| 亚洲AV无码久久寂寞少妇| 久久久久无码专区亚洲av| 国产午夜精品理论片久久影视| 久久亚洲美女精品国产精品| 久久久久国产一级毛片高清板| 国产精品99精品久久免费| 香蕉久久夜色精品国产尤物| 精品久久久久久无码人妻蜜桃| 久久久老熟女一区二区三区| 久久热这里只有精品在线观看| 久久久久亚洲AV成人网人人网站| 国产精品一区二区久久精品无码 | 狠狠色婷婷久久一区二区| 国产精品久久久天天影视香蕉| 人妻无码αv中文字幕久久琪琪布 人妻无码精品久久亚瑟影视 | 人人妻久久人人澡人人爽人人精品|