C 上的短路评估

dra*_*ine 3 c operators short-circuiting logical-operators

我正在从 Kelley-Pohl 的 A Book on C 中学习 C,有一个我不明白的练习:

int a = 0, b = 0, x;

x = 0 && (a = b = 777);
printf("%d %d %d\n", a, b, x);
x = 777 || (a = ++b);
printf("%d %d %d\n", a, b, x);
Run Code Online (Sandbox Code Playgroud)

他们只是说想象输出并将其与真实输出进行比较。我以为输出会是

777 777 0

778 778 1

但它是

0 0 0

0 0 1

Vla*_*cow 7

来自 C 标准(6.5.13 逻辑 AND 运算符)

3 && 运算符在其两个操作数比较不等于 0时应产生 1;否则,它产生 0。结果的类型为 int。

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

在这个表达式语句中

x = 0 && (a = b = 777);
Run Code Online (Sandbox Code Playgroud)

第一个操作数比较等于 0。所以第二个操作数不会被评估,即变量的值a并且b不会改变。因此,变量x0根据本节的第 3 段进行设置。

来自 C 标准(6.5.14 逻辑 OR 运算符)

3 || 如果其任一操作数比较不等于 0,则运算符应产生 1;否则,结果为 0。结果的类型为 int。

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

在这个表达式语句中

x = 777 || (a = ++b);
Run Code Online (Sandbox Code Playgroud)

第一个操作数比较不等于 0。所以第二个操作数不会被评估,即变量的值a并且b不会改变..所以变量x1根据本节的第 3 段设置。

如果您将更改表达式中操作数的顺序,例如

x = (a = b = 777) && 0;
x = (a = ++b) || 777;
Run Code Online (Sandbox Code Playgroud)

你得到了预期的结果。


ail*_*nlv 6

&&运营商使用懒惰的评价。如果&&运算符的任一侧为false,则整个表达式为false

C 检查运算符左侧的真值,在您的情况下为0。由于0在 c 中为 false (a = b = 777),因此永远不会评估操作的右侧表达式。

第二种情况是类似的,除了||返回true如果左侧表达返回true。还要记住,在 c 中,任何不是的都0被考虑true

希望这可以帮助。