C和C ++操作数解析顺序

很多时候,我看到(有时写)代码与此示例类似:

int a=0, b=2; if( a && (b=func())!=0 ) { //... 

问题是:标准是否保证这些陈述?

  1. b将不被触及(并保持值2
  2. 不会调用func()

反之亦然,如果我们写if( func()!=0 && a ) – 是否会调用标准保证func()

我对定义这个合法的特定标准段感兴趣。

UPD:我的拼写错误,从int a=1更改为int a=0

确切的问题;

问题是:标准保证这些陈述吗?

更新的问题; 给定a=0 。 如果a==0 ,则是,短路评估将启动并且不会调用func() ; 第二个操作数不会被评估。

如果a=1 (原来是),则相反; 将调用func()a1因此为“true”,因此第二个操作数被计算(它是逻辑AND), b将改变。 如果操作员已经|| (逻辑或),然后短路评估将启动并且不会调用func()

反之亦然,如果我们写if( func()!=0 && a ) – 是否会调用标准保证func()

是的,始终会评估第一个操作数。


是的,C ++保证短路评估;

§5.14逻辑AND运算符

1 &&运算符从左到右分组。 操作数都在上下文中转换为bool(第4条)。 如果两个操作数都为真,则结果为true,否则为false。 与&不同, &&保证从左到右的评估:如果第一个操作数为假,则不评估第二个操作数。

2结果是一个布尔。 如果评估第二表达式,则在与第二表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序。

§5.15逻辑OR运算符

1 || 操作员组从左到右。 操作数都在上下文中转换为bool(第4条)。 如果其任一操作数为true,则返回true,否则返回false。 与|不同 , || 保证从左到右的评估; 此外,如果第一个操作数的计算结果为true,则不计算第二个操作数。

2结果是一个布尔。 如果评估第二表达式,则在与第二表达式相关联的每个值计算和副作用之前,对与第一表达式相关联的每个值计算和副作用进行排序。


C的相应引号是;

§6.5.13逻辑AND运算符

4与按位二进制&运算符不同, &&运算符保证从左到右的评估; 如果评估第二个操作数,则在第一个和第二个操作数的评估之间存在一个序列点。 如果第一个操作数比较等于0,则不计算第二个操作数。

§6.5.14逻辑OR运算符

4与按位|不同 运算符, || 运营商保证从左到右的评估; 如果评估第二个操作数,则在第一个和第二个操作数的评估之间存在一个序列点。 如果第一个操作数比较不等于0,则不计算第二个操作数。

从C-90标准。

6.5.13逻辑AND运算符

….

4与按位二进制和运算符不同,&&运算符保证从左到右的评估; 在评估第一个操作数后有一个序列点。 如果第一个操作数比较等于0,则不计算第二个操作数。

类似地,对于逻辑OR运算符。

&&运算符要求两个操作数都为true。 如果第一个操作数的计算结果为false,则不会计算第二个操作数。 但是因为a是1,它被认为是真的,并且第二个表达式(操作数)被评估。 因此func()并将其结果分配给b然后b被测试为非零。

该标准保证了&&序列中的语句从左到右进行评估,并且只要其中一个语句的计算结果为false,就不会对其右侧的语句进行评估。

问题是:标准保证这些陈述吗?

b将不被触及(并保持值2)

不会调用func()

不,实际上他们两个都错了。 因为它是operator &&所以在这种特殊情况下不能应用快捷逻辑。

如果您将其更改为|| 那么你的陈述是正确的 – 只有那时第一个操作数的评估(在这种情况下a = 1 )才足够,其余的被忽略。


当问题变为a = 0然后是,两个语句都是正确且有保证的。