\
是一个八进制转义序列,但是9
不是有效的八进制数字,因此不是将其解释为八进制,而是将其解释为多字符常量 a\9
and a 1
其值是实现定义的。没有任何警告标志gcc
默认提供以下警告:
warning: unknown escape sequence: '\9' [enabled by default]
warning: multi-character character constant [-Wmultichar]
warning: overflow in implicit constant conversion [-Woverflow]
C99标准草案中的章节6.4.4.4
字符常量段落10 says (强调我的):
整型字符常量的类型为 int。整型字符常量的值
包含映射到单字节执行字符的单个字符是
解释为整数的映射字符表示形式的数值。包含多个字符的整型字符常量的值(例如,
'ab'),或包含不映射到单字节的字符或转义序列
执行字符,是实现定义的.
例如gcc
实施情况已记录在案here http://gcc.gnu.org/onlinedocs/cpp/Implementation_002ddefined-behavior.html如下:
编译器一次计算一个字符的多字符字符常量,将先前的值左移每个目标字符的位数,然后对截断为目标宽度的新字符的位模式进行或运算特点。最终的位模式给定类型为 int,因此无论是否对单个字符进行签名(与 3.1 版及更早版本的 GCC 略有不同),都会进行签名。如果常量中的字符多于目标 int 中可以容纳的字符,编译器会发出警告,并忽略多余的前导字符。
例如,具有 8 位字符的目标的 'ab' 将被解释为 '(int) ((unsigned char) 'a' * 256 + (unsigned char) 'b')',而 '\234a' 为'(int)((无符号字符)'\ 234'* 256 +(无符号字符)'a')'。
据我所知,这被解释为:
char c = ((unsigned char)'\71')*256 + '7' ;
这导致55
,这与多字符常量上面的实现虽然翻译\9
to \71
并不明显。
Edit
后来我意识到真正发生的事情是\
正在被丢弃,所以\9 -> 9
,所以我们真正拥有的是:
c = ((unsigned char)'9')*256 + '7' ;
这似乎更合理,但仍然任意,我不清楚为什么这不是一个直接的错误。
Update
来自阅读带注释的 C++ 参考手册我们发现在经典C在旧版本的 C++ 中,当反斜杠后面的字符未定义为转义序列时,它等于字符的数值。 ARM部分2.5.2
:
这与经典 C 和 C++ 早期版本的解释不同,其中黑斜杠后跟源字符集中的字符的序列的值(如果未定义为转义序列)等于该字符的数值。例如 '\q' 将等于 'q'。