官术网_书友最值得收藏!

1.3 詞法分析中的“貪心法”

C語(yǔ)言的某些符號(hào),例如/ 、* 、和=,只有一個(gè)字符,稱為單字符符號(hào)。而C語(yǔ)言中的其他符號(hào),例如/*和 = = ,以及標(biāo)識(shí)符,包括了多個(gè)字符,稱為多字符符號(hào)。當(dāng)C編譯器讀入一個(gè)字符'/'后又跟了一個(gè)字符'*',那么編譯器就必須做出判斷:是將其作為兩個(gè)分別的符號(hào)對(duì)待,還是合起來(lái)作為一個(gè)符號(hào)對(duì)待。C語(yǔ)言對(duì)這個(gè)問(wèn)題的解決方案可以歸納為一個(gè)很簡(jiǎn)單的規(guī)則:每一個(gè)符號(hào)應(yīng)該包含盡可能多的字符。也就是說(shuō),編譯器將程序分解成符號(hào)的方法是,從左到右一個(gè)字符一個(gè)字符地讀入,如果該字符可能組成一個(gè)符號(hào),那么再讀入下一個(gè)字符,判斷已經(jīng)讀入的兩個(gè)字符組成的字符串是否可能是一個(gè)符號(hào)的組成部分;如果可能,繼續(xù)讀入下一個(gè)字符,重復(fù)上述判斷,直到讀入的字符組成的字符串已不再可能組成一個(gè)有意義的符號(hào)。這個(gè)處理策略有時(shí)被稱為“貪心法”,或者更口語(yǔ)化一點(diǎn),稱為“大嘴法”。Kernighan與Ritchie對(duì)這個(gè)方法的表述如下,“如果(編譯器的)輸入流截至某個(gè)字符之前都已經(jīng)被分解為一個(gè)個(gè)符號(hào),那么下一個(gè)符號(hào)將包括從該字符之后可能組成一個(gè)符號(hào)的最長(zhǎng)字符串”。

需要注意的是,除了字符串與字符常量,符號(hào)的中間不能嵌有空白(空格符、制表符和換行符)。例如,==是單個(gè)符號(hào),而 = = 則是兩個(gè)符號(hào),下面的表達(dá)式

a---b

與表達(dá)式

a -- - b

的含義相同,而與

a - -- b

的含義不同。同樣,如果/是為判斷下一個(gè)符號(hào)而讀入的第一個(gè)字符,而/之后緊接著*,那么無(wú)論上下文如何,這兩個(gè)字符都將被當(dāng)作一個(gè)符號(hào)/*,表示一段注釋的開始。

根據(jù)代碼中注釋的意思,下面語(yǔ)句的本意似乎是用x除以p所指向的值,把所得的商再賦給y:

y = x/*p       /* p指向除數(shù)*/;

而實(shí)際上,/*被編譯器理解為一段注釋的開始,編譯器將不斷地讀入字符,直到*/出現(xiàn)為止。也就是說(shuō),該語(yǔ)句直接將x的值賦給y,根本不會(huì)顧及后面出現(xiàn)的p。將上面的語(yǔ)句重寫如下:

y = x / *p     /* p指向除數(shù) */;

或者更加清楚一點(diǎn),寫作:

y = x/(*p)     /* p指向除數(shù) */;

這樣得到的實(shí)際效果才是語(yǔ)句注釋所表示的原意。

諸如此類的準(zhǔn)二義性(near-ambiguity)問(wèn)題,在有的上下文環(huán)境中還有可能招致麻煩。例如,老版本的C語(yǔ)言中允許使用=+來(lái)代表現(xiàn)在+=的含義。這種老版本的C編譯器會(huì)將

a=-1;

理解為下面的語(yǔ)句

a =- 1;

亦即

a = a - 1;

因此,如果程序員的原意是

a = -1;

那么所得結(jié)果將使其大吃一驚。

另外,盡管/*看上去像一段注釋的開始,但在下例中這種老版本的編譯器會(huì)將

a=/*b;

當(dāng)作

a =/ *b ;

這種老版本的編譯器還會(huì)將復(fù)合賦值視為兩個(gè)符號(hào),因而可以毫無(wú)疑問(wèn)地處理

a >> = 1;

而一個(gè)嚴(yán)格的ANSI C編譯器則會(huì)報(bào)錯(cuò)。

主站蜘蛛池模板: 石楼县| 罗城| 北川| 炉霍县| 杭锦后旗| 东兴市| 东安县| 化州市| 扶绥县| 临西县| 普格县| 满洲里市| 保德县| 定陶县| 台南县| 通城县| 河源市| 新津县| 灌南县| 林芝县| 海原县| 车险| 清涧县| 昭通市| 惠安县| 山东| 青海省| 五指山市| 武宁县| 杭锦旗| 西乌| 始兴县| 南通市| 新平| 喀喇沁旗| 鄂伦春自治旗| 兴业县| 利辛县| 从江县| 定日县| 松潘县|