研究過 BBS source 的人應該都知道一個很有名的 BIG5 衝碼問題"壞蛋許\\n"。由於 GCC 跟 VC6 在此處的作法不太一樣。對於 GCC 而言,輸入的程式碼,是一串 bytes,而 VC6 在中文 Windows 裡,則是會把輸入的程式碼,看做是一串 big5 字元,而不只是一串 bytes 而已,所以必須用醜陋的 #ifdef 法,特別為含有「許功蓋」的 string literals[1],各寫一個版本,像這樣:

#if (ADK_COMPILER == ADK_COMPILER_MSC)
    printf("壞蛋許\n");
#else if (ADK_COMPILER == ADK_COMPILER_GCC)
    printf("壞蛋許\\n");
#endif

把輸入的程式碼,看做是一串 bytes,因此,含有反斜線的「許」字放在 string literals 裡,就必須多加一個反斜線在後面。這樣其實很難用,我常為了要讓程式可以同時 porting 在奮鬥。不過,難用歸難用,但按照 C++98,GCC 的作法,才是比較對的 (雖然也沒有算是完全正確)。

在 Standard C++ 2.2.1 裡指出:

The basic source character set consists of 96 characters: the space character, the control characters representing horizontal tab, vertical tab, form feed, and new-line, plus the following 91 graphical characters:

a b c d e f g h i j k l m n o p q r s t u v w x y z
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
0 1 2 3 4 5 6 7 8 9
_ { } [ ] # ( ) < > % : ; . ? * + - / ^ & | ~ ! = , \ " '

也就是說,在 C++ 程式碼裡面,只有這 96 個字元,才是正確可以被使用的字元,如果有需要放入這 96 個字元以外的字元,就必須要使用 Standard C++ 2.2.2 所描述的 universal-character-name construct[2] 來寫,也就是像 \u0707\U07071324 這種東西,前者後接四個十六進位數字,後者後接八個。這個數字對應到 ISO/IEC 10646 裡的字元,也就是 Unicode。

因此,實際上,我們根本不應該在程式裡面寫入任何 big5 字元,因為那不在 basic source character set 範圍裡面。

比較正確的作法,應該是引入如 gettext 或 windows resource 裡的 string table 等機制,處理這 96 個字元以外的字元。但是這樣子,真的、真的很難用。為了一個一百行不到的作業或測試程式,就要引入引入一整套 7mb 的 gettext library,以及複雜的 build 機制,甚至還得應付跨平台的問題[3]。為了殺雞還得扛把超大牛刀,甚至一整組應付不同環境的牛刀組,標準的小題大作。更別提其中隱含的歧視問題了:這 96 個字元差不多就等於 ASCII 使用者會用到的字元集,憑什麼只有 ASCII 使用者的字才是字,其他人的字就不是字?

為了這些問題,Steven Underwood 和 Nathan Myers 曾經在 gtk-i18n-list 上「熱烈地」討論過一番。不過我們也不必太悲情,basic source character set 被限制在這 96 個字元裡,多半是技術因素。C++ 已經太先進了,七年後的現在,完全達到 C++ Standard 要求的 compiler/library,還是沒有看到,如果那時候再把 Unicode 的觀念弄進來,更是沒完沒了。

事實上,C++ 的創造者 Bjarne Stroustrup[4] 曾寫過一篇有趣的論文:《Generalizing Overloading for C++2000》,裡面根本是把 source charset 推廣到極致,程式已經變成是一堆圖形的堆砌了。

延伸閱讀:


  1. 葉秉哲先生將 string literal 翻作「字串定字」。我習慣仍然用原文,如果硬要用中文的話,我認為葉秉哲先生的翻法我比較喜歡。
  2. 葉秉哲先生將 (language) construct 翻作「語言設施」。這個字比 string literal 還要難翻,我還是傾向於使用原文,但這個原文比起 string literal 來說,一般人比較看不太懂。一般來說,我認為葉秉哲先生的名詞翻譯,比較「信」也比較「達」,但相對來說,就不那麼「雅」了。翻譯真是門大學問,要信、 雅、達兼顧,真難。
  3. 因為 VC 用 string table resource
  4. 太久沒造訪,Bjarne Stroustrup 首頁的照片好像換了,從精神奕奕的鶴髮童顏,變成現在這個樣子。歲月催人老,嘆。