关于C/C++中的trigraph

来源:互联网 发布:ugui源码 编辑:程序博客网 时间:2024/06/14 16:53

 先用简单的话讲一下什么是trigraph吧,这样不会一上来就是没人看得懂的话,trigraph是三字母词,又叫三连字。

    言归正传,总得来说,thrgraph是C/C++ 为了照顾老一辈的"无产阶级革命家"而出现的,当时他们的条件极其艰苦,键盘上缺了很多键,无法输入以下九个字符:

     # \ ^ [ ] { } | ~

由此推才出现了 trigraph .

    换句话说,就是把上面的每个字符用其他三个字符来代替,替换规则如下:

 # ??= \ ??/ ^ ??' [ ??( ] ??) { ??< } ??> | ??! ~ ??-

 

下面举个例子来说明,下面是一个C++的简单程序:

#include <iostream>

using namespace std;

 

int main() {
   cout << "[]" << endl;

   return 0;
}

在当时键盘没有那九个符号的时候,那些程序员们就这么写:

??=include <iostream>

using namespace std;

 

int main() ??<
   cout << "??(??)" << endl;

   return 0;
??>

    以上内容转自百度上搜到的某个空间看到的,空间名叫"草"...

    将 trigraph 替换成对应的字符发生在预处理之前,因此 trigraph 可以在源码中的任何位置都可以用,包括字符串内,函数体开头,预处理指令等。

    有人说,如果那我就是用一个字符串常量,其中包含了 "??=" 怎么办?比如说就是要打印两个问号接一个等号,怎么办?很简单,把它拆开写, 为了打印出 "??=",我们把它拆成 "??" "=" 即可,因为 C/C++ 在处理字符串字面值的时候,会把相邻的多个字符串字面值合并成一个,而这个合并操作发生在 trigraph 替换之后,
下面的程序就可以正确的打印出两个问号和一个等号:

#include <iostream>

using namespace std;

 

int main() {
   cout << "??" "=" << endl;
}

实测中,
VC 8 不给任何提示将 trigraph 替换成对应字符,
GCC 4.0.3 则要求加上编译参数 -trigraphs 才会做相应转换。

虽然 GCC 的做法是不符合标准的,但是更加安全。
更详细的情况可以参考标准 2.3。

 

以下是从c语言参考课程里摘的一段话:

    C源程序的源字符集被包含在7位ASCII字符集中,但不是ISO 646-1983Invariant Code Set的子集。三字母(trigraph)序列允许C程序仅使用ISO(国际标准组织) Invariant Code Set编写。三字母是编译器用对应的标点字符替换的三字符序列(以两个问号开头)。你可以在C源文件中使用三字母,该源文件的字符集不能包含某些标点字符的方便图形表示。

 

    一个三字母总是作为单个源字符处理,在第一次转换阶段中,在识别字符串文字和字符常量中的转义字符之前进行三字母的转换。仅识别表1.1中列出的9个三字母,所有其它字符序列不作转换。

    字符转义序别\?防止类似三字母的字符序列被误解释(有关转义序列的信息,参见本章后面的“转义序列”)。例如,如果你试图用以下printf语句打印字符串What??!:

printf(“What??!\n");

打印的字符串What|,因为??!是一个三字母,它被|字符所替换。正确打印这个字符串的语句如下:

printf(What?\?!\n");

在这个printf语句中,在第二个问号之前加上一个反斜杠转义字符防止??!作为一个三字母的误解释。


原创粉丝点击