最近在《C陷阱與缺陷》中發現一個有意思的問題:
某些C編譯器允許嵌套註釋。請寫一個測試程序,要求:無論是對允許嵌套註釋的編譯器,還是對不允許嵌套註釋的編譯器,該程序都能正常通過編譯(無錯誤消息出現),但是這兩種情況下程序執行的結果卻不相同。
我感覺這道題對詞法的分析挺有意思的,你是不是有什麼方法可以解答?
在預處理階段,C預處理器會剔除所有出現在“/*”和“*/”之間的內容(包括這對記號本身),所以在接下來傳送到C編譯器的代碼文件裡是不會出現任何註釋內容的。
當然有不少的編譯器是不會支持嵌套註釋的。 /*/* */*/這樣是行不通的,這樣編譯去遇到的第一個*/就會結束,認為/*/**/這已經構成了一個完整的註釋。
/*/**/“1*/”/*0“/**/
你怎麼看上面這個?
這個的解決主要是利用了編譯器詞法分析中的”貪心法“
註解:貪心法就是編譯器將程序分解成符號的方法是,從左到右一個字符一個字符地進行讀入,如果該字符可能組成一個符號,那麼再讀入下一個符號,那麼再讀入下一個字符,判斷已經讀入的兩個字符組成的字符串是否可能是一個符號的組成部分;如果可能,繼續讀入下一個字符,重複上述操作,直到讀入的字符組成的字符串已經不再可能組成一個有意義的符號,這個處理策略被稱為”貪心法“,或者更通俗的說”大嘴法“
那麼我們再來看這個
/*/**/“0*/”/*1“/**/
你會怎麼處理,這一行被編譯器處理後會是什麼樣子?
好吧,直接來一起分析吧。
支持嵌套註釋的編譯器:
/*/**/“0*/ ”/*1“ /**/
得到的結果是:”/*1“
不支持嵌套註釋的編譯器:
/*/**/ “0*/” /*1“/**/
得到的結果是: “0*/”
聰明的人腳步怎麼能停下來?Doug McIlroy發現了下面這個讓人拍案叫絕的解法:
/*/*/0*/**/1
代碼如下:
#include<stdio.h>
int main(void)
{
int a = /*/*/0*/**/1;
printf("%d\n",a);
return 0;
}
如果編譯器支持嵌套註釋,a = 1 反則 a = 0
閱讀更多 Coding匠人心 的文章