我正在尝试使用以下方法在C中找到第k个斐波那契数:

int fibk(int k)
{
    if(k == 1 || k== 2)
        return 1;

    int i,a = 1,b = 1;

    for(i=3;i<=k;i++)
    {
            b = a + (a=b);
    }

    return b;
}


我之前已使用此代码交换两个变量值:

    a = a + b - (b = a)


所以我在尝试:

     b = a + (a=b);


但是此代码首先将a的值更改为b,然后简单地将其重新添加回自身,从而有效地将其值加倍,而不是将其添加到先前的值。

为什么交换代码有效,但查找下一个斐波纳契数的代码无效?

最佳答案

要回答这个问题:a = a + b - (b = a);b = a + (a=b);都具有未定义的行为。 C没有指定评估的顺序,也没有指定副作用(例如变量赋值)的发生顺序,除非有明确的序列点。因此,在以上两个表达式中,右侧的赋值都可能在访问已分配变量的值之前,之后或同时发生。 (“ while”情况涵盖了在多个机器指令中完成分配的情况,这可能是因为变量太大而无法在单个指令中存储或加载。)

“未定义的行为”就是这样-未定义。它可能会模仿您错误预期的行为;它可能只是以意外的顺序进行操作;它可能产生难以理解的垃圾;或者可以将其简单地由编译器删除,以至于什么也不会发生。或许多其他可能性。并且不能保证具有未定义行为的程序的行为将与明天编译的同一程序的行为相同。



作为一个小小的奖励,由于您似乎正在尝试避免使用临时变量,因此这是另一种斐波那契骇客,没有临时且没有UB:

int fibk(int n) {
  int a = 1, b = 0, i = n - 1;
  for (; i > 0; i -= 2) {
    b += a;
    a += b;
  }
  return i ? b : a;
}


由于它展开了循环,因此它可能会更快一些。再说一次,可能不会。 :)

关于c - 斐波那契程序中的错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/30748347/

10-11 22:10