![](/img/trans.png)
[英]C if condition comparing result of unsigned long bitwise operation with 0 is evaluated as false although true expected ( 0 == 0 is false)
[英]Comparing two equal unsigned long in C evaluates to false
我是C语言的新手,正在玩它。 因此,我最终实现了斐波那契代码(迭代和递归)。 我写了一个测试函数,应该给我一个绿色(我的实现工作正常)或红色。 它说我得到正确的返回值,但是它的状态是红色。 这两个值都应为无符号长。 我正在用make在OSX上编译
#include <stdio.h>
unsigned long fibonacci(unsigned long n);
void test_fibonacci(unsigned long n, unsigned long assertion);
int main(int argc, char* argv[])
{
test_fibonacci(1, 1);
test_fibonacci(2, 1);
test_fibonacci(3, 2);
test_fibonacci(10, 55);
return 0;
}
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult;
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
void test_fibonacci(unsigned long n, unsigned long assertion)
{
printf(
"fibonacci(%lu): %lu | %s | asserted: %lu\n",
n,
fibonacci(n),
(fibonacci(n) == assertion) ? "green" : "red",
assertion
);
}
我的Makefile
CFLAGS=-Wall -g
all: main
clean:
rm -f main
rm -Rf *.dSYM
输出:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 1 | red | asserted: 1
fibonacci(3): 2 | red | asserted: 2
fibonacci(10): 55 | red | asserted: 55
我没有得到您的输出。 这是我所看到的:
fibonacci(1): 1 | green | asserted: 1
fibonacci(2): 2 | red | asserted: 1
fibonacci(3): 4 | red | asserted: 2
fibonacci(10): 3353 | red | asserted: 55
我很好奇为什么,所以我和valgrind一起跑了。 很快弹出这个错误:
==5619== Conditional jump or move depends on uninitialised value(s)
==5619== at 0x4005E7: test_fibonacci (fibonacci.c:31)
==5619== by 0x400559: main (fibonacci.c:9)
因此,这似乎与读取未初始化的变量有关,这将为您提供错误的值。 最终,我们在这里指出:
unsigned long fibonacci(unsigned long n)
{
unsigned long result = 1;
unsigned long lastResult; // <---- LOOK HERE
for (unsigned long i = 2; i <= n; i++)
{
// save the current result to save it as the lastResult after this iteration
unsigned long lastResultTmp = result;
result = lastResult + result;
lastResult = lastResultTmp;
}
return result;
}
请注意, lastResult
未初始化,但在行中读取
result = lastResult + result;
因此,看起来您需要初始化该值。 由于该值对应于先前的斐波那契数,因此您应该初始化为零。 这样做会使所有测试通过。
现在,到底是什么原因导致它看起来像您得到了正确的答案,但仍然失败了? 请注意,您在测试代码中两次调用了fibonacci
。 我的猜测是,对fibonacci
的第一次调用-被打印出来的-只是偶然的偶然碰巧可以正常工作,因为由于某种原因,第一次调用中lastResult
的值恰好是0。但是,我猜测第二个对fibonacci
调用-与预期结果进行比较的那个调用-没有返回与第一个调用相同的值,因为无论出于何种原因,在进行第二个调用时lastResult
的值都不为0。 这就是不确定行为的事情-可能发生类似这样的奇怪事情!
fibonacci(1):1 | 绿色| 断言:1
fibonacci(2):3076653057 | 红色| 断言:1
fibonacci(3):3076653058 | 红色| 断言:2
fibonacci(10):1526988855 | 红色| 主张:55
我正在将此输出发送到您的代码。 我认为这是由于未初始化的变量lastResult所致。 因为当我用0初始化它时,我得到了正确的结果。
OP 见评论 。
这显示了测试中的一个细微弱点。 调用fibonacci(n)
时,它提供了正确的答案。 调用(fibonacci(n) == assertion)
,它提供了错误的答案。 缺点是您的测试代码每个测试两次调用fibonacci(n)
,而不是一次。 由于您的代码具有未初始化的变量: @templatetypedef
// unsigned long lastResult; // bad
unsigned long lastResult = 0; // good
使用UB(未定义的行为)-这是可能的。
测试代码应该曾经调用过一次测试函数:
unsigned long f = fibonacci(n);
printf("fibonacci(%lu): %lu | %s | asserted: %lu\n",
n, f, (f == assertion) ? `"green" : "red", assertion;
然后至少使用错误的test_fibonacci()
,更有可能获得一致的结果。
OTOH,这个弱点指出,这可能是一种优势,因为每个循环仅test_fibonacci()
一次名为test_fibonacci()
的测试,因此UB可能不会以不好的方式表现出来。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.