以下示例中的if
语句来自我正在尝试再次构建的旧项目。很抱歉,这不是一个可验证的样本,因为它不会重现错误,它自己编译得很好。
enum S { };
struct R {
S type, state;
double height;
};
int main ()
{
int rows;
S alive, rc;
double h;
R *r, *n;
// BEGIN
if ( (((r = n-1) ->type & rc) && h > r->height) ||
(((r = n+1) ->type & rc) && h > r->height) ||
(((r = n-rows)->type & rc) && h > r->height) ||
(((r = n+rows)->type & rc) && h > r->height) )
{
n->state = alive;
}
// END
}
但是,在项目中,使用相同的编译(clang 3.3,除了包含路径之外没有其他选项),它给出了
warning: multiple unsequenced modifications to 'r' [-Wunsequenced]
(指向子表达式r = n - 1
)。项目中的if
语句(标记之间BEGIN-END
)是相同的,只是变量的类型可能不同。这里定义的类型只是粗略的近似,但我认为它们与警告并不真正相关。我已经能够将表达式简化为
if( (r = n) || (r = n) ) //...
同时仍然在项目中重现警告。
我的理解是,在评估 operator 的第一个操作数之后有一个序列点&&
(||
当没有重载时)。所以我无法解释警告。
如果对表达式的形式有任何想法,无论类型如何,那都会有所帮助。
编辑
使用 Vaughn Cato 的评论,我还发现
if( ((r = n-1) ->type) || ((r = n+1) ->type) )
产生警告,而
if( bool((r = n-1) ->type) || bool((r = n+1) ->type) )
才不是。S
实际上是一个模仿枚举的类,并且有一个自定义的底层类。它重载了按位运算符&
,|
以及!
用于掩码和隐式转换运算符到底层类型,在特定情况下是size_t
. 我不知道这有多大帮助,但我很抱歉没有从一开始就披露更完整的信息。