C11中Unicode转义序列的限制
为什么C11中对Unicode转义序列(C11中Unicode转义序列的限制,c,unicode,escaping,string-literals,unicode-escapes,C,Unicode,Escaping,String Literals,Unicode Escapes,为什么C11中对Unicode转义序列(\unnn和\unnnnn)有限制,只有基本字符集之外的字符可以表示?例如,以下代码导致编译器错误:\u000A不是有效的通用字符。(一些Unicode“dictionary”网站甚至将这种无效格式作为C/C++语言的标准格式,尽管无可否认,这些格式可能是自动生成的): static inline int test\u unicode\u single(){ 返回strlen(u8“\u000A”)>1; } 虽然我知道这些基本字符并不一定要被支持,但有
\unnn
和\unnnnn
)有限制,只有基本字符集之外的字符可以表示?例如,以下代码导致编译器错误:\u000A不是有效的通用字符
。(一些Unicode“dictionary”网站甚至将这种无效格式作为C/C++语言的标准格式,尽管无可否认,这些格式可能是自动生成的):
static inline int test\u unicode\u single(){
返回strlen(u8“\u000A”)>1;
}
虽然我知道这些基本字符并不一定要被支持,但有没有一个技术上的原因使它们不能被支持呢?比如不能以多种方式表示同一个字符?这恰恰是为了避免使用其他拼写 < >对C和C++添加通用字符名称(UCNS)的主要动机是:
- 允许标识符包含基本源字符集之外的字母(例如
)ñ
- 允许使用可移植机制写入字符串和字符文字,其中包括基本源字符集之外的字符
ñ
,作为两个字节0xc3、0xb1或六字符序列\u00D1
,它们最终都将作为相同的字节序列。这反过来意味着每个标识符只有一个拼写,因此不需要(例如)更改符号表查找
通常,编译器只是通过编译管道传递变量名,让汇编器或链接器最终处理它们。如果这些下游工具不接受扩展字符编码或UCS(取决于实现策略),则需要对包含此类字符的名称进行“篡改”(转录),以使其可接受。但即使这是必要的,这只是一个小小的改变,可以在一个定义良好的接口上完成
<>而不是解决产品(或开发团队)在两种策略之间有明确偏好的编译器厂商之间的争论,C和C++标准委员会选择了机制和限制,使两者兼容。特别是,两个委员会都禁止使用表示基本源字符集中已有编码的字符的UCS。这避免了以下问题:
- 如果我将
放入字符串文本中,会发生什么情况:\u0022
如果编译器将UCS转换为它们所表示的字符,那么当词法分析器看到该行时,const char* quote = "\u0022";
将已转换为“\u0022”
,这是一个词法错误。另一方面,将UCS保留到最后的编译器很乐意将其作为字符串文本接受。禁止使用表示引号的UCN可以避免这种可能的不可移植性”““
- 类似地,
是否为换行符?同样,如果UCN在第1阶段转换为反斜杠,那么在第3阶段,字符串文字肯定会被视为换行符。但是,如果UCN仅在字符文字标记被标识为字符值之后才转换为字符值,则生成的字符文字将包含两个字符(实现定义的值)'\u005cn'
- 那么
呢?即使UCS不应该用于标点符号,这看起来会像是一种添加吗?或者它看起来像一个以非字母代码开头的标识符2\u002b2
const char* s = "\\
n";
const char* s = "\n";