0

我已经在代码块中编译了下面的代码,它显示了输出 0...0 。但我认为它的输出应该是 0...1,因为这里的“if”语句不正确,所以“if”后面的语句不会被执行。然后 j 增加 1(因为“if”语句中的 j++)但是i 仍然为 0。所以,最后一个 printf() 应该给出 0...1。

#include <stdio.h>

int main()
{
    int i =0,j=0;
    if(i && j++)
        printf("%d..%d\n",i++,j);
    printf("%d...%d",i,j);
    return 0;
}
4

9 回答 9

3

由于iis 0(falsy),没有理由执行j++. 这叫短路。

它在检查中很有用if(a < v.size() && v[a] == 5) // do something

于 2013-07-16T16:14:39.557 回答
3

参见C11 6.5.13 逻辑与运算符 p4(我的重点)

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

您示例中的第一个操作数是i. 它比较等于 0,因此j++不会评估(执行)第二个操作数 ( )。因此,您后来的printf显示j仍然为 0 是正确的。

于 2013-07-16T16:17:15.367 回答
0

条件 ( ) 的第一部分已经为假,因此不执行i第二部分 ( )。j++

于 2013-07-16T16:14:01.857 回答
0

你不会得到递增j。看看你的 if 语句:

if(i && j++)

只有当iANDj都为真时,才执行 if 块。但既然i已经是假的,甚至不需要检查j++。它也称为短路评估

于 2013-07-16T16:15:08.503 回答
0

没有应用 if 条件中 j 的增量的原因是因为该表达式被短路了——即 i 永远不会非零,因此不需要计算第二个表达式。

于 2013-07-16T16:15:32.407 回答
0

不要使用逻辑与&&,而是使用按位与&,只要iandj0or ,它就不会短路并按照您想要的方式工作1

...
if(i & j++)
    printf("%d..%d\n",i++,j);

或者如果他们不是:

if (!!i & !!(j++))
   ...
于 2013-07-16T16:16:48.897 回答
0

j++表达式未执行,因为第一个条件(运算符左侧)的评估已经i返回&&false,因此j++不评估第二个条件。

这是编译器进行的常见优化,通常称为短路条件评估,在某些编译器中您可能会关闭此优化,以避免这种副作用。

于 2013-07-16T16:17:18.637 回答
0

正如您在此示例代码中看到的,从您的源代码中第二个 IF 未执行:

    movl    i(%rip), %eax       
    testl   %eax, %eax          ; <-- if i
    je  .L2
    movl    j(%rip), %eax
    testl   %eax, %eax          ; <-- if j Not EXECUTED !!!
    setne   %dl 
    addl    $1, %eax            ; <-- j++
    movl    %eax, j(%rip)
    testb   %dl, %dl
    je  .L2
    ...                         ; inner IF
.j2

如另一个答案中所述。

于 2013-07-16T16:55:23.547 回答
0

正如您所提到的,如果声明为假,则为真。但我认为使用的概念/逻辑在某些地方不合适,原因会随之而来。

在此之前让我们了解 &&(Logical AND) 运算符的工作原理。如果声明如果与它关联的两个操作数都为真,那么只有结果为真。注意: 1. 对于编译器,这意味着如果任何一个操作数为假,编译器将不会进一步计算,即跳到下一个有效的代码行。2. 0(零)状态为假 - 在编程中。

好吧,编译器首先搜索运算符,然后查找与之关联的操作数。

因此,一旦编译器遇到“&&”,它就会查看运算符的左侧,因为 &&(Logical AND) 的关联性是从左到右的,并评估左侧操作数的值为 0(零)。现在,参考注释 2 和注释 1。

因此,编译器跳转到下一个有效语句 printf("%d...%d",i,j);

这里,变量“j”没有增加,因此“j”的值将保持为 0(零)。

注意:为了进一步弄清楚这个想法,我建议尝试使用不同的 i 和 j 值的相同示例,例如 i=1 和 j=1 或 i=2 和 j=1。

于 2013-07-16T17:06:30.190 回答