以下代码为我提供了编译器警告
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) )
{
;
}
}
答案 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)()) )
{
;
}
双重点的一点是它可以作为具有明确意图的单个操作读取,而其他任何东西都必须由读取器解码。