三元表达式 VC2008 的解析无效?
Invalid parse of ternary expression VC2008?
下面的代码给我一个编译器警告
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) )
{
;
}
}
简而言之,这是违反约束。首先,赋值表达式的类型由左侧确定。所以你的案例看到 struct XTYPE*
和 struct YTYPE*
.
6.5.16 Assignment operators - p3
An assignment operator stores a value in the object designated by the
left operand. An assignment expression has the value of the left
operand after the assignment,111) but is not an lvalue. The type of an
assignment expression is the type the left operand would have after
lvalue conversion. The side effect of updating the stored value of the
left operand is sequenced after the value computations of the left and
right operands. The evaluations of the operands are unsequenced.
并且条件表达式的操作数类型必须满足此约束:
6.5.15 Conditional operator - p3
One of the following shall hold for the second and third operands:
- both operands have arithmetic type;
- both operands have the same structure or union type;
- both operands have void type;
- both operands are pointers to qualified or unqualified versions of compatible types;
- one operand is a pointer and the other is a null pointer constant; or
- one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of void.
因为 struct XTYPE*
和 struct YTYPE*
不是指向兼容类型的指针( 可能 甚至适用的唯一项目符号),实际上只是指向的指针不相关的类型,你的程序格式错误。
这里的一个主要争论点是 MSVC 不是一个符合标准的 C 编译器(无论如何都不是 C11)。但是自从 MSVC 支持的最后一个 C 版本以来,上述规则并没有太大变化,所以你知道了。
虽然您没有使用它,但编译器必须通过查看两个 RHS 路径来为三级操作的结果创建一个合理的类型。
在第一种情况下,你给了它 2 个不相关的指针类型 X 和 Y,它拒绝为 if 语句直接解析为 bool。 (bool 在 C 中不作为特定类型存在,因此需要使用一些 int 类型)
在第二种情况下,通过与 0/NULL/nullptr 进行比较,您将此转换为 bool,尽管您已将逻辑从 if set
切换为 if clear
。
在c++中我们有继承和相关类型的概念,所以编译器经常可以找到一个通用的类型来解决这些语句。根据我的经验,不同的编译器对这种情况的处理方式不同,但是如果有严格的合规性设置,它应该总是失败,除非其中一个操作数是另一个操作数的子类型。
过去我用来解决这些问题的一种方法是使用 "double-pling" !!作为保持原始意义的布尔值的转换:
if (b ? !!(pX= (*pfFoo)())
: !!(pY= (*pfFoo)()) )
{
;
}
double-pling 的要点在于它可以作为具有明确意图的单个操作来读取,而其他任何内容都必须由 reader 解码。
下面的代码给我一个编译器警告
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) )
{
;
}
}
简而言之,这是违反约束。首先,赋值表达式的类型由左侧确定。所以你的案例看到 struct XTYPE*
和 struct YTYPE*
.
6.5.16 Assignment operators - p3
An assignment operator stores a value in the object designated by the left operand. An assignment expression has the value of the left operand after the assignment,111) but is not an lvalue. The type of an assignment expression is the type the left operand would have after lvalue conversion. The side effect of updating the stored value of the left operand is sequenced after the value computations of the left and right operands. The evaluations of the operands are unsequenced.
并且条件表达式的操作数类型必须满足此约束:
6.5.15 Conditional operator - p3
One of the following shall hold for the second and third operands:
- both operands have arithmetic type;
- both operands have the same structure or union type;
- both operands have void type;
- both operands are pointers to qualified or unqualified versions of compatible types;
- one operand is a pointer and the other is a null pointer constant; or
- one operand is a pointer to an object type and the other is a pointer to a qualified or unqualified version of void.
因为 struct XTYPE*
和 struct YTYPE*
不是指向兼容类型的指针( 可能 甚至适用的唯一项目符号),实际上只是指向的指针不相关的类型,你的程序格式错误。
这里的一个主要争论点是 MSVC 不是一个符合标准的 C 编译器(无论如何都不是 C11)。但是自从 MSVC 支持的最后一个 C 版本以来,上述规则并没有太大变化,所以你知道了。
虽然您没有使用它,但编译器必须通过查看两个 RHS 路径来为三级操作的结果创建一个合理的类型。 在第一种情况下,你给了它 2 个不相关的指针类型 X 和 Y,它拒绝为 if 语句直接解析为 bool。 (bool 在 C 中不作为特定类型存在,因此需要使用一些 int 类型)
在第二种情况下,通过与 0/NULL/nullptr 进行比较,您将此转换为 bool,尽管您已将逻辑从 if set
切换为 if clear
。
在c++中我们有继承和相关类型的概念,所以编译器经常可以找到一个通用的类型来解决这些语句。根据我的经验,不同的编译器对这种情况的处理方式不同,但是如果有严格的合规性设置,它应该总是失败,除非其中一个操作数是另一个操作数的子类型。
过去我用来解决这些问题的一种方法是使用 "double-pling" !!作为保持原始意义的布尔值的转换:
if (b ? !!(pX= (*pfFoo)())
: !!(pY= (*pfFoo)()) )
{
;
}
double-pling 的要点在于它可以作为具有明确意图的单个操作来读取,而其他任何内容都必须由 reader 解码。