C++句法歧义及消解方法

0. 引言
 
 C++中的句法歧义主要由类似int (a)的代码引起,此类代码共有3种合法的结构解释:
    第一种是声明符a两边具有冗余圆括号的对象声明,其等同于int a;
    第二种是函数式转型,它是表达式的一种,其等同于(int) a;
    第三种是函数类型标识符,其等同于int f(a b)。
    既然一种代码可同时解释为声明、表达式和类型,根据排列组合,共可引发声明和表达式、声明和类型、表达式和类型之间的3类歧义,这3类歧义均无法通过句法消解。上述3类两两之间的歧义在C++中都存在对应的句法构造,所幸的是C++中不存在声明、表达式和类型都能同时存在的地方,否则将需要消解3个对象,而不是现在的2个。下面对3类歧义对应的句法构造、带来的影响和消解的办法进行详细说明。
 
1. 声明 vs. 表达式
 
    C++中的语句结构可以是一个声明(声明语句),也可以是一个表达式(表达式语句),所以在解析语句的时候需要对声明和表达式进行歧义消解。C++标准的6.8节规定声明的优先级大于表达式的优先级,既优先将一个构造看成是声明。如此一来编译器在解析类似int (a);的代码时,优先将其看成是一个整型变量a的声明。具体实现的办法是使用trial模式对代码进行句法解析(gcc中称为tentative parse),在trial模式下,编译器首先尝试以某种构造解析代码,如果无句法错误,则将代码解析为此种构造,否则以另一种构造解析代码。首先尝试解析的通常是优先级高的构造,所以在对声明语句和表达式语句消岐的时候,编译器首先尝试将歧义代码解析为声明语句,如果失败则按表达式语句语法对代码进行匹配。由于采用了trial模式进行歧义消解,所以对于歧义语句代码,编译器只会报告表达式语句错误信息,而不会报告声明语句错误信息。
    声明和表达式的歧义还出现在函数声明及具有函数式初始化体的对象声明中。看如下代码:
        int a = 0;
        int f(int (a));
    上述代码中f的声明具有两种合法的解析方式:第一种是函数声明,即将int (a)解析为声明;第二种是对象声明,即将int (a)解析为函数式转型表达式,f声明代码等价于int f = (int)a。C++标准规定的消岐方式还是遵循声明优先的原则,即优先将int (a)解析为声明,所以C++编译器优先将f解析为函数声明,而不是具有初始化体的对象声明。
 
2. 声明 vs. 类型   
    声明和类型的歧义出现在函数参数构造中。参看如下代码:
    class a;
    int f(int (a));
    上述代码中函数f的参数类型具有两种合法的解释:第一种情况是参数类型为整型,参数名为a(将代码int (a)解析为声明),此种情况下函数声明代码等同于int f(int a);第二种情况是参数类型为函数,参数名省略(将代码int (a)解析为类型),此种情况下函数声明代码等同于int f(int (*cp)(a b))。C++标准规定的消岐方式是优先将int (a)解析为类型,也就是优先将范例代码中的函数声明解析为第二种情况,具体可参见标准的8.2节第7款。
 
3. 表达式 vs. 类型
    在sizeof和typeid操作符的操作数中存在表达式和类型的歧义,因为它们的操作数既可以是一个表达式也可以是一个类型标识符。它们的句法结构如下:
    postfix_expression:
        "typeid" '(' ( expression | type_id ) ')'
    unary_expression:
        "sizeof" ( unary_expression | '(' type_id ')' )  
    看一个存在歧义的范例代码:
        class a;
        sizeof(int (a));
    上述代码的两种解析方式为:操作符为函数式转型表达式的sizeof表达式,即将int (a)解析为表达式,上述代码等同于sizeof((int) a);操作符为函数类型的sizeof表达式,既将int (a)解析为类型,上述代码等同于sizeof(int f(a b))。C++标准规定的消岐方式是优先将int (a)解析为类型,也就是优先将范例代码中的sizeof表达式解析为第二种情况。
 
4. 后记
 
    从上述分析可以看出,C++标准优先将类似int (a)的代码解释为类型,其次是声明,最后才是表达式,并结合trial模式对此类歧义构造进行消解。标准还规定,消岐的过程是纯句法的,不可使用语义信息,唯一可使用的语义信息是判断一个名字是否为类型名。
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值