【问题标题】:why '\97' ascii value equals 55为什么 '\97' ascii 值等于 55
【发布时间】:2015-10-10 03:28:09
【问题描述】:

就像C代码:

#include<stdio.h>

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

结果是55,但我不明白如何计算。 我知道'\'后面是八进制数或十六进制数,97 是十六进制数吗?

【问题讨论】:

    标签: c ascii


    【解决方案1】:

    \ 是八进制转义序列,但 9 不是有效的八进制数字,因此不是将其解释为八进制,而是将其解释为多字符常量 \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 的实现记录在here 中,如下所示:

    编译器一次计算一个字符的多字符字符常量,将前一个值左移每个目标字符的位数,然后在截断到宽度的新字符的位模式中进行或运算的目标人物。最终的位模式被赋予 int 类型,因此是有符号的,无论单个字符是否有符号(与 GCC 3.1 和更早的版本略有不同)。如果常量中的字符多于目标 int 中的字符数,编译器会发出警告,并忽略多余的前导字符。

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

    据我所知,这被解释为:

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

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

    编辑

    我后来意识到真正发生的事情是 \ 正在被删除,所以 \9 -&gt; 9,所以我们真正拥有的是:

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

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

    更新

    通过阅读带注释的 C++ 参考手册,我们发现在 Classic C 和旧版本的 C++ 中,当反斜杠后面的字符未定义为转义序列时,它是相等的到字符的数值。 ARM部分2.5.2

    这与经典 C 和 C++ 的早期版本的解释不同,其中黑斜线序列的值后跟源字符集中的字符,如果未定义为转义序列,则等于数值的性格。例如 '\q' 将等于 'q'。

    【讨论】:

      【解决方案2】:

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

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

      edit:Shafik 指出它不是未定义的,而是已定义的实现。请参阅他的答案以获取参考资料。

      【讨论】:

        【解决方案3】:

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

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

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

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

        【讨论】:

          【解决方案4】:

          \9 不是有效的转义序列,因此它可能会退回到普通的 9 字符。

          这意味着它与 '97' 相同,这是 undefined 实现定义的(参见 Shafik Yaghmour 的回答)行为(2 个字符不能放入 1 个字符...)。


          为避免将来发生此类情况,请考虑在编译器上增加警告。例如,gcc 的最小值应为 -Wall -Wextra -pedantic

          【讨论】:

          • @ShafikYaghmour 啊。我很长时间没有使用默认编译器设置,所以不知道。如果是这种情况,那么 OP 应该已经看到了警告并能够从那里找出来......:/
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-07-07
          • 2010-10-07
          • 2015-02-06
          • 1970-01-01
          • 1970-01-01
          • 2018-03-29
          • 1970-01-01
          相关资源
          最近更新 更多