C语言中双字符组(digraph)和三字符组(trigraph)的使用注意事项

某些标点符号,在一些键盘上是无法输入的,所以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)进行预编译转换处理的。

 

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

于是程序就这样了:

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值