转载:http://blog.csdn.net/dqjyong/article/details/8048829
在编写程序时需要时时提防编译器背着我们干一些没有通知我们做的事,下面列举转义字符对程序的影响。
首先列出二字符组和三字符组对应的意思。
二元字符
等价字符
<:
[
:>
]
<%
{
%>
}
%:或者%%
#
三元字符 等价字符
??=
#
??/
\
??'
^
??(
[
??)
]
??!
|
??<
{
??>
}
??-
~
值得庆幸的是,二元字符或者三元字符转义之后不能再与二元字符或者三元字符结合,要不然程序员可能会疯了。闲话少说,那么为什么会c++标准允许出现这种情况呢?
1.由于类似“#\”等这些字符在EBCDIC的代码页中用来区分代码点的。在所有的EBCDIC的代码页中使用“?”和"="不会分割代码页,而会共享同一个代码点。
2.其次是因为一些国际化的键盘设置原因,有些键盘没有这些字符对应的按键,而这些字符又必须在一些文本中使用,因此采用一些替代方法。
言归正传,总得来说,thrgraph是C/C++ 为了照顾老一辈的"无产阶级革命家"而出现的,当时他们的条件极其艰苦,键盘上缺了很多键,无法输入以下九个字符:
由此推才出现了 trigraph .
| |
| |
| |
| |
| |
| |
| |
| |
| |
知道了原因,接下来看看让程序员摸不着头脑的错误代码(其实不是语法错误,而是程序运行的结果会让你大吃一惊)。
情形1:
#include <iostream>
int main()
{
int x = 1;
for( int i = 0; i < 100; ++i );
// What will the next line do? Increment???????????/
++x;
std::cout << x;
}
情形2:
#include <iostream>
int main()
{
int x = 1;
for( int i = 0; i < 100; ++i )
// What will the next line do? Increment???????????/
++x;
std::cout << x;
}
即要使用trigraphs在编译时需要添加上-trigraphs参数。因此未加-trigraphs参数时,得出的结果与细心的读者预料的结果一致。而加上-trigraphs参数之后,那么结果你可能就得好好分析了。这里我们知道了注释行存在一个三元转义符"??/",其对应得符号为"\",而"\"将其下面得一行代码也作为注释,所以情形1实际的代码为:
#include <iostream>
int main()
{
int x = 1;
for( int i = 0; i < 100; ++i );
std::cout << x;
}
#include <iostream>
int main()
{
int x = 1;
for( int i = 0; i < 100; ++i )
std::cout << x;
}
因此情形1的输出为: 1
下面举个例子来说明,下面是一个C++的简单程序:
#include <iostream>
using namespace std;
int main() {
}
在当时键盘没有那九个符号的时候,那些程序员们就这么写:
??=include <iostream>
using namespace std;
int main() ??<
??>
下面的程序就可以正确的打印出两个问号和一个等号:
#include <iostream>
using namespace std;
int main() {
}
实测中,
VC 8 不给任何提示将 trigraph 替换成对应字符,
GCC 4.0.3 则要求加上编译参数 -trigraphs 才会做相应转换。
虽然 GCC 的做法是不符合标准的,但是更加安全。
更详细的情况可以参考标准 2.3。
以下是从c语言参考课程里摘的一段话:
printf(“What??!\n");
打印的字符串What|,因为??!是一个三字母,它被|字符所替换。正确打印这个字符串的语句如下:
printf(What?\?!\n");
在这个printf语句中,在第二个问号之前加上一个反斜杠转义字符防止??!作为一个三字母的误解释。
使用得最多的、最普遍的是ASCII字符编码, 即American Standard Code for Information Interchange, 如表1所示。
从表中可以看到:
每个字符是用7位基2码表示的, 其排列次序为b6b5b4b3b2b1b0, 在表中的b6b5b4为高位部分, b3b2b31b0为低位部分。而一个字符在计算机内实际上用8位表示。正常情况下, 最高一位b7为 "0"。在需要奇偶校验时, 这一位可用于存放奇偶校验的值, 此时称这一位为校验位。
表1 ASCII字符编码表
b6b5b4
| 000 001 010 011 100 101 110 111 |
b3b2b1b0 |
-
|
0 0 0 0 0 0 0 1 0 0 1 0 0 0 1 1 0 1 0 0 0 1 0 1 0 1 1 0 0 1 1 1 1 0 0 0 1 0 0 1 1 0 1 0 1 0 1 1 1 1 0 0 1 1 0 1 1 1 1 0 1 1 1 1 | NUL DLE SP 0 @ P 、 p SOH DC1 ! 1 A Q a q STX DC2 " 2 B R b r ETX DC3 # 3 C S c s EOT DC4 $ 4 D T d t ENQ NAK % 5 E U e u ACK SYN & 6 F V f v BEL ETB ' 7 G W g w BS CAN ( 8 H X h x HT EM ) 9 I Y I y LF SUB * : J Z j z VT ESC + ; K [ k { FF FS , < L \ l | CR GS - = M ] m } SO RS . > N ↑ m ~ SI US / ? O - o DEL |
ASCII是128个字符组成的字符集。其中编码值0-31不对应任何可印刷(或称有字形)字符, 通常称它们为控制字符, 用于通信中的通信控制或对计算机设备的功能控制。编码值为32的是空格(或间隔)字符SP。编码值为127的是删除控制DEL码。其余的94个字符称为可印刷字符,有人把空格也计入可印刷字符时,则称有95个可印刷字符。请注意, 这种字符编码中有如下两个规律:
(1)字符0-9这10个数字符的高3位编码为011, 低4 位为000-1001。当去掉高3位的值时, 低4位正好是二进制形式的0-9。这既满足正常的排序关系, 又有利于完成ASCII码与二进制码之间的类型转换。
(2)英文字母的编码值满足正常的字母排序关系, 且大、小写英文字母编码的对应关系相当简便, 差别仅表现在b5一位的值为0或1, 有利于大、小写字母之间的编码变换。
另有一种字符编码,是主要用在IBM计算机中的EBCDIC代码(Extended Binary Coded Decimal Interchange Code)。它采用8位码, 有256个编码状态, 但只选用其中一部分。0-9十个数字符的高4位编码为1111, 低4位仍为0000-1001。大、小写英文字母的编码同样满足正常的排序要求, 而且有简单的对应关系, 即同一个字母的大小写的编码值仅最高的第二位的值不同, 易于识别与变换。