6

我一直在尝试了解八进制数的 printf 功能。如果我将代码编写为:

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

它给了我一个作为 S 的输出,它实际上是正确的,因为 S 的 ASCII 是八进制的 123。但我的问题是,编译器如何识别要从八进制转换的数字序列。例如:

char *s = "\123456" 

将输出为 S456

八进制转换最多需要3个数字吗???

是否应该给出八进制数的最大限制(最大 3 位八进制数为 777)

现在因为最多有 255 个 ascii 字符(八进制 377),所以当我尝试打印 777 时,它会打印一个典型的 ascii 字符,这可能是因为没有分配给这个数字的 ascii。这个功能也依赖于编译器/操作系统???

我希望非常清楚,因为这是我的第一个问题:-)

4

3 回答 3

9
  1. 是的。三个数字是八进制字符文字的最大值。从规范6.4.4.4 字符常量

    八进制转义序列:八进制数字八进制数字八进制数字八进制数字八进制数字八进制数字
    \
    \
    \

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

  2. \777正如您所提到的,最大的八进制转义序列。从上面的规范引用中可以看出,十六进制转义序列没有最大限制。

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

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

    在大多数机器上,unsigned char是 8 位类型,\377在该上下文中将八进制转义序列限制为,将十六进制序列限制为\xff. 在 32 位wchar_t上下文的情况下,十六进制序列可能高达\xffffffff.

于 2013-02-11T06:36:46.997 回答
3

C99 标准(我可以查看的标准)octal-escape-sequence对字符串的定义如下:

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

因此,anyoctal-escape-sequence最多有 3 个八进制数字(0to 7)。

解释简单地说:

八进制转义序列中反斜杠后面的八进制数字被视为整数字符常量的单个字符或宽字符常量的单个宽字符构造的一部分。如此形成的八进制整数的数值指定所需字符或宽字符的值。

还,

每个八进制或十六进制转义序列都是可以构成转义序列的最长字符序列。

以及以下约束:

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

\777因此,如果最多使用 8 位 ( CHAR_BIT< 9) ,则值违反约束。我在规范中找不到有关此的内容,我猜这是未定义的行为,因此取决于编译器。

于 2013-02-11T06:37:49.927 回答
0

在数字前加上“0”,编译器会将其标识为八进制。例如:0123

将“0x”放在数字之前将其标识为编译器的十六进制。例如:0x123

否则为十进制。例如:123

字符 *s = "\123456"

对于您的示例转义序列,\123 是十进制数。编译器只知道使用 3 位数字,因为字符的范围是 0-255,因此它将限制为 3 位数字。

顺便说一句,十进制 123 的字符是“S”,这就是你的字符串是“S456”的原因。

于 2013-02-11T06:36:25.623 回答