某些标点符号,在一些键盘上是无法输入的,所以C提供了这样的替换方式。其中双字符记号有六个,也成为双字符组(digraph):
<: [
:> ]
<% {
%> }
%: #
%:%:
##
如果上述任何字符组出现在字符常量或字符串字面值中,则不会被解释成双字符组;除此之外,它们一律被解释成双字符组,作用和相应的单一字符记号完全一样。比方说,下列的两个程序代码片段完全等价的,并且会产生相同的执行结果。
有双字符组的程序版本:
printf( "Hello,world!My age is <%d>./n", arr<:1:> );
没有双字符组的程序版本:
int arr[ ] = { 10, 20, 30 };printf( "Hello,world!My age is <%d>./n", arr[1] );
输出:Hello,world!My age is <3>. ※假设arr[1]被赋值为3,:)
同样的,最初同事E遇到的问题,实际上是C语言中的三字符组(trigraph),也就是三个字符的表示方式。这样的字符有9个, 它们全都是以两个问号开始,由第三个字符决定三字符组所表示的标点符号是什么.
利用三字符组,实际上我们只需要使用ISO/IEC 646 所定义的字符,就可以写出任何C 程序(ISO/IEC646 是1991 年发布的7 位ASCII 标准)
下面是维基百科中关于ISO/IEC 646的解释:
ISO/IEC 646是国际标准化组织(ISO)和国际电工委员会(IEC)制订的标准,在1972年制订。它是一个 7-位元字符的字集,来自数个国家标准,最主要来自美国的 ASCII(美国信息互换标准代码)。ISO 646 除了英语字母和数字的部分,为所有国家相同外,有些使用字母的国家,可按照实际需要,把 ISO 646 作出修改,以定出该国的字符标准。亦因为当年 8-位元字符集并未得到普遍的接纳,各国把不同的字母或符号放进它们的字符集,以致部分出现在 ASCII 的字母或符号,并没有出现在某些国家的 ISO 646 变体之中。
由于发生在编译的第一个阶段,编译器的预处理器会将三字符组取代成单一对等字符,也就是说会被翻译成等价的字符,不管它们出现在何处,甚至出现在字符常量、字符串字面值、注释,或者预处理指令中,也一样会被取代,这和双字符组的做法不一样。
最初的问题,其实之所以有这样的输出,是因为C/C++编译器在编译的第一个阶段,也就是预处理阶段所做的处理。
但是有很多时候我们并不希望被解释为三字符组,这个时候我们可以把问号表示成转义符(escape sequence):
printf("Exit this application/?/?/?(y/n)");
这样就不会被解释为三字符组了。另外要注意的是,如果用的是Gcc编译器,默认的是不对双字符组(digraph)和三字符组(trigraph)进行预编译转换处理的。
#: ??=
/: ??/
^: ??’
[: ??(
]: ??)
{: ??<
}:
??>
|: ??!
~: ??-
于是程序就这样了:
本文介绍了C语言中双字符组(digraph)和三字符组(trigraph)的概念及其使用方法。详细解释了这些特殊字符组如何帮助开发者在有限的字符集中编写程序,以及如何避免它们在不期望的情况下被误解释。
1162

被折叠的 条评论
为什么被折叠?



