【问题标题】:Invalid parse of ternary expression VC2008?三元表达式VC2008解析无效?
【发布时间】:2018-02-14 17:32:42
【问题描述】:

下面的代码给了我一个编译器警告

warning C4133: ':' : incompatible types - from 'YTYPE *' to 'XTYPE *'

但是,对我来说,expession 似乎还可以。有什么想法吗?

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


    【解决方案1】:

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

    6.5.16 Assignment operators - p3

    赋值运算符将值存储在由 左操作数。赋值表达式具有左边的值 赋值后的操作数,111) 但不是左值。 类型 赋值表达式是左操作数之后的类型 左值转换。 更新存储的值的副作用 左操作数在左的值计算之后排序,并且 右操作数。操作数的计算是无序的。

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

    6.5.15 Conditional operator - p3

    第二个和第三个操作数应满足以下条件之一:

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

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


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

    【讨论】:

    • 我明白了。虽然我的意图是三元表达式的任一分支的结果都将被测试为零,但两个分支的结果必须是相同的类型。通过显式编写测试(第二个示例),它们现在已成为布尔表达式,因此是兼容的。
    【解决方案2】:

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

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

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

    过去我用来解决这些问题的一种方法是使用“双打”!作为保持原始含义的布尔值:

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

    双重化的意义在于,它可以被视为具有明确意图的单个操作,而其他任何内容都必须由阅读器解码。

    【讨论】:

      猜你喜欢
      • 2014-12-25
      • 2014-11-12
      • 2013-01-17
      • 2018-02-12
      • 2020-07-30
      • 2017-09-22
      • 1970-01-01
      • 2021-07-19
      • 2017-07-05
      相关资源
      最近更新 更多