【问题标题】:C program interesting behaviourC 程序有趣的行为
【发布时间】:2012-09-29 06:57:06
【问题描述】:

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

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

#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++ 时没有任何反应。

谁能解释为什么会这样?

【问题讨论】:

  • i++ &amp;&amp; iterator++ -> i++, iterator++
  • 这个问题可能很基础,但问得很完美。
  • 就像我说的,我知道如何正确地做,我只是想找出为什么上面的代码没有按我预期的方式工作。

标签: c for-loop


【解决方案1】:

事情是iterator++ 实际上不是第一次执行。 ++ 运算符返回变量的当前值,then 递增它,所以第一次通过时,i++ 将等于 0&amp;&amp; 短路,所以iterator++ 第一次没有被执行。

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

【讨论】:

  • 这很有趣,我确实知道 && 运算符不会评估表达式的第二部分,如果第一个部分已经为假,但我没想到它会适用,因为它不是t 放在循环语句的条件部分。谢谢你的回答。 10分钟后我会批准。
  • 您可以阅读有关短路评估的更多信息。 &&、|| 有多种规则等
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

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

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

    i 为0(在第一次迭代中)时,i++ 给出0 作为结果,所以它是假的,所以iterator++ 不会被执行。

    【讨论】:

    • 我用Visual Studio很久了,最近换了linux,还没学会如何使用控制台调试器,不过我会研究一下。
    • 这个故事的寓意是始终将-Wall 传递给gcc 并改进您的代码,直到没有给出警告为止。你甚至可以将-Wall -Wextra -g 传递给gcc
    • @lonut Hulub 您仍然可以在 Linux 中使用 Eclipse 进行图形调试器。然而,gdb(控制台调试器)是一项有价值的技能,特别是当您在没有 UI 的平台上工作时。
    • AFAIK,用于 C 的 Eclipse 调试器只是 gdb 的 GUI 界面(就像 ddd 一样)。所以学习gdb还是有用的。
    【解决方案4】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-02-03
      • 2014-02-04
      • 1970-01-01
      • 2017-02-07
      • 2010-11-26
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多