为什么’\’97’ascii值等于55

就像C代码一样:

#include int main(void) { char c = '\97'; printf("%d",c); return 0; } 

结果是55 ,但我无法理解如何计算它。 我知道八进制数或hex数跟在’\’后, 97是hex数吗?

\是八进制转义序列,但9不是有效的八进制数字,因此它不是将其解释为八进制,而是被解释为多字符常量a \91其值是实现定义的。 没有任何警告标志, gcc默认提供以下警告:

 warning: unknown escape sequence: '\9' [enabled by default] warning: multi-character character constant [-Wmultichar] warning: overflow in implicit constant conversion [-Woverflow] 

6.4.4.4节中的C99标准草案字符常量10段说( 强调我的 ):

整数字符常量的类型为int。 包含映射到单字节执行字符的单个字符的整数字符常量的值是解释为整数的映射字符的表示的数值。 包含多个字符(例如,’ab’)的整数字符常量的值,或包含未映射到单字节执行字符的字符或转义序列的值是实现定义的

例如, 此处记录了 gcc实现,如下所示:

编译器一次评估一个字符的多字符字符常量,将前一个值移动每个目标字符的位数,然后在截断到目标宽度的新字符的位模式中输入字符。 最终的位模式为int类型,因此无论单个字符是否有符号都是有符号的(与版本3.1及更早版本的GCC略有不同)。 如果常量中的字符数多于目标int中的字符数,则编译器会发出警告,并忽略多余的前导字符。

例如,具有8位字符的目标的’ab’将被解释为’(int)((unsigned char)’a’* 256 +(unsigned char)’b’)’和’\ 234a’as ‘(int)((unsigned char)’\ 234’* 256 +(unsigned char)’a’)’。

据我所知,这被解释为:

 char c = ((unsigned char)'\71')*256 + '7' ; 

这导致55 ,这与上面的多字符常量实现一致,尽管\9\71的转换不明显。

编辑

我后来意识到真正发生的是\正在被丢弃,所以\9 -> 9 ,所以我们真正拥有的是:

 c = ((unsigned char)'9')*256 + '7' ; 

这似乎更合理,但仍然是武断的,不清楚为什么这不是一个直接的错误。

更新

通过阅读Annotated C ++ Reference Manual,我们发现在Classic C和旧版本的C ++中,当反斜杠后跟字符未定义为scape序列时,它等于字符的数值。 ARM部分2.5.2

这与Classic C和早期版本的C ++的解释不同,其中,如果未定义为转义序列,则源字符集中的字符后面的黑色字符串的值等于字符的数值。 例如’\ q’将等于’q’。

\ 9不是有效的转义符,因此编译器忽略它并且ascii’7’为55。

我不会依赖这种行为,它可能是未定义的。 但这就是55来自哪里。

编辑:Shafik指出它没有未定义,它是实现定义的。 请参阅他的答案参考。

首先,我将假设您的代码应该读取此内容,因为它与您的标题相匹配。

 #include int main(void) { char c = '\97'; printf("%d",c); return 0; } 

\9无效,因此我们假设该字符实际为7. 7是ascii 55,这是打印出来的答案。

我不确定你想要什么,但是\97不是它……

\9不是有效的转义序列,所以它可能会回落到普通的9字符。

这意味着它与'97'是一样'97' ,它是未定义的实现定义(参见Shafik Yaghmour的答案)行为(2个字符不能适合1个字符……)。


为避免将来出现这种情况,请考虑在编译器上启动警告。 例如, gcc的最小值应为-Wall -Wextra -pedantic