6

我偶然发现了一段代码,它在调试别人的程序时会产生一些有趣的结果。

我创建了一个小程序来说明这种行为:

#include <stdio.h>

int main()
{
        char* word = "foobar"; int i, iterator = 0;
        for (i = 0; i < 6; i++ && iterator++)
          printf("%c", word[iterator]);
        return 0;
}

我知道这不是打印字符串的正确方法。这仅用于演示目的。

在这里,我显然希望输出是“foobar”,但实际上是“ffooba”。基本上它会读取第一个字符两次,就好像第一次iterator++执行没有任何反应一样。

谁能解释为什么会这样?

4

4 回答 4

11

事情iterator++实际上不是第一次执行。运算符返回变量的++当前值,然后将其递增,因此第一次通过时,i++将等于0&&短路,所以iterator++不是第一次执行。

要解决此问题,您可以使用无条件评估两者的逗号运算符,而不是短路&&.

于 2012-09-29T07:00:08.693 回答
5

的结果i++是第一次迭代时的当前值i为零。由于短路,这意味着 iterator++在第一次迭代时不执行(仅当左侧为“真”时才执行右侧&&

要解决此问题,您可以使用逗号运算符(如已经建议的那样)使用++i它将i在增量之后返回值(尽管逗号运算符更明显,必须始终对两者进行评估)。

于 2012-09-29T06:59:46.150 回答
3

你真的应该学会使用像 eg 这样的调试器gdb,并使用警告和调试信息gcc -Wall -g(假设是 Linux 系统)进行编译。最近gcc的 with-Wall会警告您在操作之前未使用计算的值&&

for循环的增量部分很奇怪。它是i++ && iterator++(但应该是i++, iterator++)。

Wheni为 0(在第一次迭代中),i++结果为 0,因此为 false,因此iterator++不执行。

于 2012-09-29T07:01:13.297 回答
2

我正在阅读有关逻辑运算符的K&R,让我引用书中的原话,这可以解释您的问题。“由 && 或 || 连接的表达式从左到右进行评估,一旦知道结果的真假,评估就会停止。” 对这些有很好的理解,输出不会令人困惑。

于 2012-09-29T12:29:54.187 回答