atiken插值c++_C++,那些可爱的小陷阱(三)

我们沿袭忠于标准的传统,还是首先来看一个标准中的例子

??=define arraycheck(a,b) a??(b??) ??!??! b??(a??)

这真是一段XE的代码,你看懂什么意思了么?好吧这次厚道点立刻上答案:

#define arraycheck(a,b) a[b] || b[a]

这个代码尽管是用来演示三元转义符的,但是我看到这个宏定义暗示另一个非常古怪的语法,在没有重载[]运算符的情况下,a[b]和b[a]总是完全等价的。所以在任何你使用了a[1]的时候,你都可以替换成1[a],尽管这看起来非常诡异。似乎这一点颇得标准编写者的喜爱,居然在一个完全无关的场合明里暗里地提了一下这个事情。

好吧我们言归正传,这些诡异的用法是C++的三元转义符,所幸它们数量不多,请看下表:

三元符

用以替代

三元符

用以替代

三元符

用以替代

??=

#

??(

[

??<

{

??/

\

??)

]

??>

}

??'

^

??!

|

??-

~

注意一点我们的例子是一个宏定义,这很好地说明了三元转义符是在编译过程的最开始处理,它的优先权也是最高的,不论在任何位置(包括注释和字符串中)三元符都会被转义。也许记忆所有转义有些困难,但是编写C++时注意两个问号相连的情况就可以安全了。

关于三元转义符有个悲情的故事,(本故事根据Exceptional C++某段改编)故事讲的是某粗心的软件工程师在写注释的时候留了一个问题:Is it necessary?由于他想要加强语气他决定多写些问号,于是他按住shift和?键,但是很遗憾他shift松得早了一点,最后一个?就变成了/(看看你的键盘就明白了)于是他的注释变成了:

//Is it necessary??????????????????????????????/

这看起来再正常不过了,注释里的文字错误又不会有什么影响,然而??/却是一个三元符,于是转义之后注释变成了:

//Is it necessary????????????????????????????\

到这里想必您已经看明白了,最后一个\成为一个续行符,于是这行注释吞掉了下一行代码。这个问题,我目前还未发现有什么编译环境能够正确地识别出来(语法着色无法反映三元转义符),所以一旦发生,很难检查。

悲剧版Hello world:(看到没,博客园的代码高亮也识别不出来)

#includeintmain()

{//Isn't it right??????????????????????????????/printf("Hello world!\n");

}

跟三元转义符相似,C++里面还有一种token替代语法,跟三元转义符相比,它们不是纯文本替换,它们自己是token的一种,可以算作对应token的别名,数量则稍微多了点:

替代的

原有的

替代的

原有的

替代的

原有的

{

and

&&

and_eq

&=

%>

}

bitor

|

or_eq

|=

<:>

[

or

||

xor_eq

^=

:>

]

xor

^

not

!

%:

#

compl

~

not_eq

!=

:%

##

bitand

&

这个规则不会替换字符串和注释中的符号。

三元转义符和token替代的存在最初都是为了某些非ANSI计算机文本环境存在的,虽说到现在意义已经不是很大,但是我们编程的时候还是要特别注意,不要让这些过时的语言特性变成我们代码中的地雷。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值