通过 'printf' 命令打印八进制数。

6

我一直在尝试理解printf对于八进制数字的功能。

如果我将代码写成:

int main()
{
  char *s = "\123";
  printf("%s", s);
}

它给我输出了S,这实际上是正确的,因为S的ASCII在八进制中是123。

但编译器如何识别要从八进制转换的数字序列呢?例如:

char *s = "\123456"

会输出 S456。

是不是八进制转换最多只能有三个数字?

八进制的最大限制是多少(最大的三位数八进制数是777)。

现在,由于最多只有255个ASCII字符(八进制377),所以当我尝试打印777时,它会打印一个典型的� ASCII字符,我认为这可能是因为没有将此数字分配给任何ASCII字符。 此功能是否取决于编译器/操作系统?


1
只有128个ASCII字符。 - Carl Norum
3个回答

9
  1. 是的。一个八进制字符字面量的最大位数为三位。参考规范6.4.4.4 Character constants:

    octal-escape-sequence:
    \ octal-digit
    \ octal-digit octal-digit
    \ octal-digit octal-digit octal-digit

    hexadecimal-escape-sequence:
    \x hexadecimal-digit
    hexadecimal-escape-sequence hexadecimal-digit

  2. 如您所述,最大的八进制转义序列为\777。对于十六进制转义序列没有最大限制,如上所述。

  3. 只有128个ASCII字符(0-127)。这意味着您可以使用八进制\000\177表示ASCII。如果使用不同的字符集,则可以在8位char中使用\377,并且对于可以一直使用\777(或更高,使用十六进制转义序列)。规范说明:

    整型字符常量的八进制或十六进制转义序列的值应在类型unsigned char的可表示值范围内,宽字符常量的无符号类型对应于。

    在大多数机器上,unsigned char是一个8位类型,在该上下文中将八进制转义序列限制为\377,并且十六进制序列限制为\xff。在32位上下文中,十六进制序列可以高达\xffffffff


感谢卡尔提供了深入的解决方案,我非常感激。 - Anshul

3

C99标准(我能查看的那个版本)将字符串的octal-escape-sequence定义为:

octal-escape-sequence:
    \ octal-digit
    \ octal-digit octal-digit
    \ octal-digit octal-digit octal-digit

因此,任何八进制转义序列最多具有3个八进制数字(07)。
简单来说,解释如下:
在八进制转义序列中反斜杠后面的八进制数字被视为整数字符常量或宽字符常量的单个字符构造的一部分。由此形成的八进制整数的数值指定所需字符或宽字符的值。
另外,
每个八进制或十六进制转义序列都是可以构成转义序列的最长字符序列。
以下是一个约束条件:
对于整数字符常量,八进制或十六进制转义序列的值应在类型unsigned char的可表示值范围内,对于宽字符常量应在对应于wchar_t的无符号类型的范围内。
因此,如果使用了不超过8位(CHAR_BIT < 9),则值为\777违反了约束条件。我在规范中找不到关于这方面的内容,我想这是未定义行为,因此取决于编译器。

1
如果CHAR_BIT大于等于9,则\777是合法的。 wchar_t也可能足够大以适应\777。 它很可能是16位或更大。 - Carl Norum
1
\777是实现定义(在一个8位字符平台上),而不是未定义行为(6.4.4.4/10)。 - Michael Burr
谢谢,已删除该部分。 - Mihai Maruseac

0
将数字前面加'0'可使编译器将其识别为八进制数。例如:0123
在数字前面加'0x'可使编译器将其识别为十六进制数。例如:0x123
否则它就是十进制的。例如:123
char *s = "\123456"

对于你的转义序列示例,\123 是一个十进制数。编译器知道只使用三个数字,因为字符范围从0到255,因此它将在三个数字上限制。


3
错误。 ASCII 123(十进制)是“ {”。这个答案怎么会得到赞成票呢? - Carl Norum
你说得对,我错了。但是我不知道为什么它会将那个转义序列作为八进制数来解释。我想我需要再看看。 - PQuinn
因为这就是规范定义的内容。没有十进制转义序列。 - Carl Norum
八进制数123对应的十进制数是83,它对应的字符是S。 - Anshul
1
@Lundin:转义值本质上不必是八进制的。某个时候,有人做出了这个决定。如果转义是十进制的,就像我想的那样,那么该字符串将是“{456”,而不是“123456”。 转义仍然适用且仍然需要。 - PQuinn
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接