在C中解释反斜杠

任何人都可以解释下面的代码,并请解释反斜杠( \ )在这种情况下的作用。 什么\'\"\ooo\ \\?是什么意思?

 #include  int main(){ char a = '\010'; char y = '010'; printf("%d,%d",a,y); return 0; } 

输出:8,48

这个'\010'是一个八进制转义序列 10 ,八进制是十进制的8 ,当调用printf时它将被提升为一个int ,以便解释该值。

这个'010'是一个多字符常量 ,它的值是实现定义的,如果我们看一下C99草案标准部分6.4.4.4 字符常量10段说( 强调我的 ):

[…]包含多个字符(例如,’ab’)的整数字符常量的值,或包含未映射到单字节执行字符的字符或转义序列的值是实现定义的。[ …]

如果你使用gcc你至少会看到这个警告:

警告:多字符字符常量[-Wmultichar]

溢出时可能还有这个警告:

警告:隐式常量转换溢出[-Woverflow]

y获得的值更有趣,因为字符常量具有整数值,它不能只取第一个字符, 多字符常量必须取数值然后转换为charclang提供更详细的警告:

警告:从’int’到’char’的隐式转换将值从3158320更改为48 [-Wordstant-conversion]

当前版本的gcc产生相同的值,我们可以从这段简单的代码中看到:

 printf("%d\n",'010'); 

3158320来自哪里? 至少对于gcc ,如果我们查看实现定义行为的文档,它会说:

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

如果我们执行上面的操作( 假设8位字符 )文档,我们看到:

  48*2^16 + 49*2^8 + 48 = 3158320 ^ ^ | decimal value of ASCII '1' decimal value of ASCII '0' 

gcc将使用模数2^8int转换为char ,无论char是有符号还是无符号 ,这实际上留下了最后8位或48

它是一个转义序列,用于删除某些保留字符的含义,例如'或指定一些特殊字符,例如换行符'\n'或者在这种情况下是具有特定ASCII值的字符:

 char a = '\010'; 

定义八进制ASCII值为10 8的字符,即十进制值8 10

 char y = '010'; 

定义一个多字节字符,应该分配给宽字符,而不是char 。 虽然未定义此赋值的行为,但在这种情况下,它很可能会导致在y中存储最后一个字符

在第一种情况下, \010被解释为八进制,结果为8

在第二种情况下,返回ascii值0010的第一个字符),即48

如果你有编译器警告,很可能你已经想到了第二个

 char y = '010'; 

靠自己。 (在这种情况下, gcc会发出-Wmultichar-Woverflow 。)


引用C1X草案 ,第6.4.4.4节:

整数字符常量的类型为int 。 包含映射到单字节执行字符的单个字符的整数字符常量的值是解释为整数的映射字符的表示的数值。 包含多个字符(例如, 'ab' )的整数字符常量的值,或包含未映射到单字节执行字符的字符或转义序列的值是实现定义的 。 如果整数字符常量包含单个字符或转义序列,则其值是当char的类型为单个字符或转义序列的对象转换为int类型时生成的值。

希望这可以帮助:

 \a Beep \b Backspace \f Formfeed \n New line \r Carriage return \t Horizontal tab \v Vertical tab \\ Backslash \' Single quotation mark \" Double quotation mark \0 ASCII 0x00 (nul terminator) \ooo Octal representation \xdd Hexadecimal representation \xnn Hexadecimal character code nn \onn Octal character code nn \nn Octal character code nn 

转义序列是包含反斜杠(\)后跟某个字符的字符组合。 当您使用几乎所有语言进行编程时,有时您需要参考不会产生特定字符的按键。

例如,假设您开发了一个假设变量用Box括号[var]括起来的语言 – 那么如果您输入的值不是变量,那么您将必须像\[10\]那样转义它。 否则,您的编译器会认为10是变量名。

这是一个转义序列 – 请参阅http://en.wikipedia.org/wiki/Escape_sequences_in_C