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

问题描述 投票:2回答:2

以下代码给出了编译器警告

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) )
    {
        ;
    }
}
c visual-studio ternary-operator
2个回答
3
投票

简单来说,这是违反约束的行为。首先,赋值表达式的类型由左侧确定。所以你的案子看到struct XTYPE*struct YTYPE*

6.5.16 Assignment operators - p3

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

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

6.5.15 Conditional operator - p3

下列之一应适用于第二和第三操作数:

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

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


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


0
投票

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

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

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

我过去用来解决这些问题的一种方法是使用“双重打击”!!作为布尔保持原始意义的强制转换:

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

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

© www.soinside.com 2019 - 2024. All rights reserved.