按整数限定符打印字符

8

我正在尝试执行以下程序。

#‎include‬ "stdio.h" 
#include "string.h" 

void main()
{ 
    char c='\08'; 
    printf("%d",c); 
} 

我得到的输出是56。但对于除8之外的任何数字,输出都是该数字本身,但对于8,答案是56。有人能解释一下吗?

请将代码放在问题中(注意**{}**格式化按钮),并添加有意义的标题。(编辑按钮就在问题下方)。 - BoBTFish
4
因为未定义行为是未定义的。 - molbdnilo
1
我敢打赌你的编译器正在抱怨c的定义是一个多字符常量... - DarkDust
1
@molbdnilo:这不是未定义行为;它是实现定义的,这是不同的。 - Eric Postpischil
@EricPostpischil 我会期望在这种情况下适用于“如果任何参数不是相应转换说明符的正确类型,则行为未定义”。不是吗? - molbdnilo
显示剩余4条评论
4个回答

18

\0 开头的字符表示八进制数,是一种使用数字0到7的八进制数字系统。因此,\08八进制数的无效表示形式,因为8 ∉ [0, 7],因此会出现实现定义的行为。

可能你的编译器将多字节字符'\08'识别为一个'\0'字符和一个'8'字符并解释为'\08''\0'+'8',从而变成了'8'。查看ASCII表后,您会注意到'8'的十进制值为56。


感谢 @DarkDust、@GrijeshChauhan 和 @EricPostpischil。

2
GCC和clang都抱怨这是一个多字符常量,因此它们似乎将其解释为字符'\0' + '8'。而且,'8' == ASCII十进制56。 - DarkDust
2
请问,给我点踩的人能否解释一下原因,这样我才能从中吸取经验,这个问题很有意思,我真的想知道我是对还是错。 - Maroun
1
\ 开头的字符表示八进制数是有点错误的,应该是 \0,你忘了加 0 - Grijesh Chauhan
3
这不是未定义行为,而是实现定义的行为。根据C 2011 (N1570)规范6.4.4.4第1条规定,字符常量可以是一个字符序列。在'\08'中,\0被认为是一个字符,8则是另一个字符。这被称为多字节字符(而不是多字符常量)。根据6.4.4.4第2条规定,它以一种实现定义的方式映射到执行字符集的一个成员。 - Eric Postpischil
2
@GrijeshChauhan:这些不是多字符常量,而是多字节字符。C语言实现可能支持比基本字符集更大的字符集。它们可能包括带重音的字符、来自不同语言或符号的字母。多字节字符是一种表示这些字符的源代码编写方式之一。 - Eric Postpischil
显示剩余6条评论

8
'\08'被视为多字符常量,由\0(计算值为0)和ASCII字符8(计算值为56)组成。它的解释是实现定义的。C99标准如下所述:
整数字符常量的类型为int。包含映射到单字节执行字符的单个字符的整数字符常量的值是表示映射字符的值的整数。包含多于一个字符(例如'ab')或包含未映射到单字节执行字符的字符或转义序列的整数字符常量是实现定义的。如果整数字符常量包含单个字符或转义序列,则其值是将值为该单个字符或转义序列的char类型对象转换为int类型时产生的值。
因此,如果您将'\08'分配给比char更大的东西,比如intlong,它甚至还有效。但是,由于您将其分配给了char,因此您正在“截断”某些部分。哪一部分可能也取决于实现/机器。在您的情况下,它会为您提供8的值(ASCII字符,计算值为56)。
GCC和Clang都会通过"warning: multi-character character constant"来警告这个问题。

1
记录一下:Visual C++ 2010会发出警告"C4125:十进制数字终止了八进制转义序列",但您必须设置/W4(警告级别)选项,其中/W3是默认值。 - Wacek

4

\0在C/C++中用于表示八进制数。八进制基数的数字范围是0->7,所以\08是一个多字符常量,由\0组成,编译器将\08解释为\0+8,因此它变成了'8',其ascii值为56。这就是为什么你会得到56作为输出结果。


Umer的 '\08' 应该是未定义的,由实现定义。 - Grijesh Chauhan

4

正如其他答案所说,这些数字表示八进制字符(基数为8)。这意味着您必须写'\010'代表数字8,'\011'代表数字9等。

还有其他编写赋值的方法:

char c = 8;
char c = '\x8'; // hexadecimal (base 16) numbers 

@Roddy - 不正确。在C/C++中,数字文字前缀为0表示八进制表示法--而不是二进制。 - Justin ᚅᚔᚈᚄᚒᚔ

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