字节顺序标记真的是有效的标识符吗?

时间:2011-11-22 13:31:32

标签: c++ unicode c++11 byte-order-mark

C ++ 11对标识符(§E)中允许的Unicode代码点列表进行了大量添加。这包括字节顺序标记,它包含在范围FE47-FFFD中。

咨询角色浏览器,此范围包括一大堆随机内容,从WHITE SESAME DOTPRESENTATION FORM FOR VERTICAL LEFT SQUARE BRACKET开始,包括一些“小标点符号”,花式阿拉伯语, BOM出现在这里,半宽和全宽亚洲字符,最后包括REPLACEMENT CHARACTER,通常用于指示损坏的文本呈现。

当然这是某种错误。他们觉得有必要排除“芝麻点”,无论那些是什么,但字节顺序标记a.k.a.弃用的零宽度不间断空间是公平的游戏?当另一个零宽度不间断空格a.k.a. word joiner在C ++ 11中也被认为是可接受的标识符时?

似乎对标准的最优雅的解释是,将任何形式的Unicode定义为源字符集,是在可选BOM之后开始该文件。但是,用户也可以通过使用BOM作为标识符来合法地开始文件。这太丑了。

我错过了什么,或者这是一个毫无疑问的缺陷?

3 个答案:

答案 0 :(得分:4)

我尝试解释:标准只规定了抽象源代码的规则。

您的编译器带有“源字符集”的概念,它告诉它如何编码具体的源代码文件。如果该编码是“UTF-16”(即没有BE / LE说明符,因此需要BOM),那么BOM不是代码点流的一部分,而只是文件包络的一部分。

文件解码后只有才能将代码点流传递给编译器。

答案 1 :(得分:4)

首先,我想说你所描述的问题不太重要。如果您的编译器需要UTF-8 BOM以便将文件视为使用UTF-8编码,那么您不能拥有缺少UTF-8 BOM的文件,但源文件以UTF-8编码的U + FEFF开头。如果您的编译器不需要UTF-8 BOM来处理UTF-8文件,那么您不应该在源文件中放置UTF-8 BOM(用Michael Kaplan的话来说,"STOP USING WINDOWS NOTEPAD")。

但是,是的,如果编译器剥离BOM,那么您可以获得与预期不同的行为。如果你想(不明智地)用U + FEFF开始一个源文件,但(明智地)拒绝将BOM放在你的源中,那么你可以使用通用字符名称:\ uFEFF。

现在回答我的问题。

C ++标准未定义物理源文件字符的检索。向编译器声明源文件编码,用于存储物理源字符的文件格式以及将物理源文件字符映射到基本源字符集都是实现定义的。支持在源文件的开头处理U + FEFF作为编码提示位于此区域。

如果编译器支持可选的UTF-8 BOM并且不能在提供可选BOM的文件之间进行区分,而不是源代码以U + FEFF开头,则这是编译器设计中的缺陷,更广泛地说是UTF-8 BOM本身的想法。

为了将数据字节解释为文本,必须知道文本编码,由权威来源明确确定。 (Here's一篇提出这一观点的文章。)不幸的是,在理解这个校长之前,数据已经在系统之间传输,人们不得不处理表面上是文本但编码不一定已知的数据。所以他们提出了一个非常糟糕的解决方案:猜测。涉及UTF-8 BOM的一组技术是开发的猜测方法之一。

出于某些原因,选择UTF-8 BOM作为编码提示。首先,它对可见文本没有影响,因此可以在没有可见效果的情况下故意插入到文本中。其次,非UTF-8文件不太可能包含被误认为UTF-8 BOM的字节。但是,这些并不妨碍使用BOM而不是猜测。没有任何说明ISO-8859-1纯文本文件不能以U + 00EF U + 00BB U + 00BF开头。在ISO-8859-1中编码的这一字符序列与以UTF-8编码的U + FEFF共享相同的编码:0xEF 0xBB 0xBF。依赖于检测UTF-8 BOM的任何软件都会被这样的ISO-8859-1文件混淆。因此,即使基于它的猜测几乎总是有效,BOM也不能成为权威来源。

除了使用UTF-8 BOM相当于猜测之外,还有第二个原因,这是一个糟糕的主意。这就是错误的假设,即对文本的视觉显示没有影响的文本更改根本没有效果。每当文本用于视觉显示之外的其他内容时,这种假设可能是错误的,例如当它在文本中用于计算机作为源代码读取时。

总之:UTF-8 BOM的这个问题不是由C ++规范引起的;除非你绝对被迫与需要它的脑死程序交互(换句话说,只能处理以U + FEFF开头的Unicode字符串子集的程序),不要使用UTF-8 BOM。 / p>

答案 2 :(得分:0)

C ++规范的那部分(以及您的问题)与unicode规范相关联。想想,在任何正常的unicode文件中,文件中可能会出现FFFE(或其他),那么我们应该如何解释这些呢?

根据unicode标准,流/文件开头的BOM char不会被视为字符,在演示文稿中会被忽略。

当他们说'C ++文件可以是unicode格式'时,他们也将所有C ++规范都绑定到unicode规范。这里的unicode法也控制着C ++规范。

因为unicode标准已经定义了这种行为(在开头跳过BOM),C ++标准的编写者有充分的理由不将它包含在他们的文档中。任何实现unicode C ++编译器的人都会考虑unicode标准。