三元表达式VC2008的解析无效?

时间:2018-02-14 17:32:42

标签: c visual-studio ternary-operator

以下代码为我提供了编译器警告

warning C4133: ':' : incompatible types - from 'YTYPE *' to 'XTYPE *'
然而,对我而言,这次尝试似乎没问题。有什么想法吗?

struct XTYPE {
    int x;
    long y;
};
struct YTYPE {
    long y;
    int x;
};

extern void *getSomething(void);

void Test(void)
{
    int b= 0;
    struct XTYPE *pX;
    struct YTYPE *pY;

    void * (*pfFoo)(void);

    pfFoo= getSomething;

    if (b ? (pX= (*pfFoo)())       // error
          : (pY= (*pfFoo)()) )
    {
        ;
    }
    if (b ? ((pX= (*pfFoo)())!=0)  // no error
          : ((pY= (*pfFoo)())!=0) )
    {
        ;
    }
}

2 个答案:

答案 0 :(得分:3)

违反约束条款,简单地说就是这样。首先,赋值表达式的类型由左侧确定。因此,您的案例会看到struct XTYPE*struct YTYPE*

6.5.16 Assignment operators - p3

  

赋值运算符将值存储在由指定的对象中   左操作数。赋值表达式的值为left   赋值后的操作数,111)但不是左值。 的类型   赋值表达式是左操作数之后的类型   左值转换。更新存储值的副作用   左操作数在左和右的值计算之后排序   正确的操作数。对操作数的评估是不合理的。

条件表达式的操作数类型必须满足此约束:

6.5.15 Conditional operator - p3

  

以下其中一项适用于第二和第三个操作数:

     
      
  • 两个操作数都有算术类型;
  •   
  • 两个操作数具有相同的结构或联合类型;
  •   
  • 两个操作数都有void类型;
  •   
  • 两个操作数都指向兼容类型的限定或非限定版本的指针;
  •   
  • 一个操作数是指针,另一个是空指针常量;或
  •   
  • 一个操作数是指向对象类型的指针,另一个是指向合格或非限定版本的void的指针。
  •   

由于struct XTYPE*struct YTYPE*不是兼容类型的指针(可能甚至适用的唯一项目符号),并且实际上只是指向不相关类型的指针,因此您的程序是不正确的。

<子> 这里争论的一个主要问题是MSVC不是一个符合C的编译器(无论如何不是C11)。但是自从MSVC 支持支持的最后一个C版本以来,上述规则没有太大变化,所以你有它。

答案 1 :(得分:0)

虽然您没有使用它,但编译器必须通过查看两个RHS路径为第三个操作的结果制作一个合理的类型。 在第一种情况下,你给了它2个不相关的指针类型X和Y,它拒绝直接解析为if语句的bool。 (bool在C中不作为特定类型存在,因此需要使用某种int类型)

在第二种情况下,通过与0 / NULL / nullptr进行比较,您已经将此强制转换为bool,尽管您已将逻辑从if set切换为if clear

在c ++中,我们有继承和相关类型的概念,因此编译器通常可以找到一个通用类型来解析这些类型的语句。根据我的经验,不同的编译器对这种情况的处理方式不同,但是在严格的符合性设置下,它应该总是失败,除非其中一个操作数是另一个操作数的子类型。

过去我用来解决这些问题的一种方法是使用&#34; double-pling&#34; !作为保持原始意义的布尔值:

 if (b ? !!(pX= (*pfFoo)())
       : !!(pY= (*pfFoo)()) )
 {
    ;
 }

双重点的一点是它可以作为具有明确意图的单个操作读取,而其他任何东西都必须由读取器解码。