c/c++ 字符編碼與標識符

說明:html

      對於比較現代的語言來說字符編碼不是個大問題:java就能夠使用中文做爲變量名稱,但對於C/C++來說卻不是這樣,因爲歷史緣由,標準和編譯器廠商的實現總在不停的變化,相關編碼信息究竟是如何處理的?對於想知道相關信息的新手來說是很難從現有的書籍和資料上來找到明確的答案。針對這個問題我就本身的理解並結合相關的標準試圖向讀者把這個問題講清楚,因爲編譯器衆多,因此重點就放在對標準的解釋以及相關文檔的說明上,具體的實驗和測試請自行操做。java

  標識符(Identifer)定義(C99和C++2003中的定義是一致的,C89中沒有規定universal-character-name且對標識符長度有規定,C99中不對長度做限定,C++2003規定能夠是任意長度):git

Syntax windows

1 identifier: identifier-nondigit app

identifier identifier-nondigit identifier digit ide

identifier-nondigit: nondigit 函數

universal-character-name 工具

other implementation-defined characters 測試

ISO/IEC 9899:1999 (E) ui

nondigit: one of _ 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

digit: one of 0 1 2 3 4 5 6 7 8 9 

      從廣義上來說字符編碼實際上有兩種,一種是multibyte,另外一種是unicode,multibyte編碼對字符內容的解釋取決於當前系統的區域設置,如windows下的cp936(中文編碼)編碼就是一種multibyte編碼。unicode編碼與系統的當前編碼沒有相關性;在各平臺上都應該能正確處理;實際上與UCS編碼(ISO/IEC 10646)是兼容的。unicode是一種編碼方式的統稱,事實上它包含多種編碼如:utf-8,utf-16等。那麼對於字符編碼在C語言的相關標準又是怎麼規定的呢?ANSI C標準(既C89)明確規定multibyte字符只能應用在字符串字面量,註釋、字符常量這三個方面。對於標識符而言(變量名、函數名等)只能使用基本字符(其實是26個字母)與數字以及下劃線,而且不容許以數字開頭,具體的編譯器至少要能正確處理31個長度的標識符名稱(C89標準 5.2.1.2)。可見早期的編譯器從標準角度來看是沒法處理mulibyte和unicode標識符的,但實際上具體的編譯器實現可能做出了擴展以容許標識符字符進行擴展,例如GNU的擴展選項-fextended-identifiers。隨着標準的發展此問題獲得瞭解決,C99標準明確規定multibyte和universal-character-name能夠做爲標識符的名字(C99標準 5.2.1.2)。至於C++,2003標準只規定了基本拉丁字符、數字、下劃線以及universal-character-name,而multibyte由具體的編譯器實現決定。可見因爲標準的變化以及相關編譯器的實現異差,在實際工做應該只使用基本的拉丁字符、數字、下劃線用做標識符,這樣才能保證可移植性。

相關編譯器信息:

GNU 3.1

http://gcc.gnu.org/onlinedocs/gcc-3.1/gcc/Identifiers-implementation.html

Identifiers

  • Which additional multibyte characters may appear in identifiers and their correspondence to universal character names (6.4.2).
  • The number of significant initial characters in an identifier (5.2.4.1, 6.4.2)
  • 更早版本的相關信息無從考證了。若有疑問請自行google。

VS2003:

Visual C++ .NET 2003 Enhanced Compiler Conformance

In this version of the compiler, Unicode characters that cannot be represented in the current system code page are not allowed. The compiler's support for Unicode characters and universal-character-names, as specified in ISO/ANSI Standard, is as follows:

  • Comments

  • String and character literals

  •  

    可見在這個版本支持仍是進分有限的,不支持multibyte只支持universal-character-names 

VS2005

http://msdn.microsoft.com/zh-cn/library/vstudio/xwy0e8f2(v=vs.100).aspx

文件名

如今能夠在命令行和編譯器指令(如 #include)中指定的文件名中包含 Unicode 字符。 在 Visual C++ 的早期版本中,僅支持 ANSI 文件名。 在輸出文件名中應避免非 ASCII 字符,以即可執行文件可在 Windows 98 和 Windows Me 的本地化版本上運行。

源代碼文件

如今,標識符、宏、字符串和字符文本以及註釋中均支持 Unicode 字符。 如今也支持通用字符名稱。

可按如下編碼格式將 Unicode 字符輸入到源代碼文件中:

  • 具備或不具備字節順序標記 (BOM) 的 UTF-16 Little Endian

  • 具備或不具備 BOM 的 UTF-16 Big Endian

  • 具備 BOM 的 UTF-8

Output

在編譯期間,編譯器以 UTF-16 格式將診斷輸出到控制檯。 可在控制檯顯示的字符由控制檯窗口屬性決定。 重定向到文件的編譯器輸出位於當前 ANSI 控制檯代碼頁中。

連接器響應文件和 .DEF 文件

響應文件和 DEF 文件能夠是具備字節順序標記的 UTF-16,也能夠是 ANSI。 之前僅支持 ANSI。

.asm 和 .cod 轉儲

默認狀況下,.asm 和 .cod 轉儲爲 ANSI 格式,以便兼容 MASM。 使用 /FAu 則輸出 UTF-8。 請注意,若是指定 /FAs,則將只是直接輸出混合源文件,並且可能會顯示爲亂碼,例如,當源代碼爲 UTF-8 而且未指定 /FAsu 時。

能夠經過選擇合適的工具以及選擇「啓用 Unicode 響應文件」屬性(默認爲啓用)在開發環境中啓用 Unicode 文件名(請參見 如何:打開項目屬性頁)。 有些狀況下須要更改此默認值,例如要修改開發環境以便使用不具備 Unicode 支持的編譯器時。

VS2005對multibyte和unicode支持的都很完善了。後繼的VS2008-VS2012與VS2005在此方面基本沒有差別。若是感興趣可另行查找相關資料。

LLVM 3.3

Clang supports Unicode characters in identifiers and its static analyser has added new checkers and can run interprocedural analyses across C++ constructor/destructor boundaries.

最後

      事不辯不清,理不論不明。歡迎就此老是一塊兒討論。

相關文章
相關標籤/搜索