如何调试这段C代码
当我在一个网站上读到一些问题时,我遇到了下面的一个问题,其中一个c问题需要调试如何调试这段C代码,c,C,当我在一个网站上读到一些问题时,我遇到了下面的一个问题,其中一个c问题需要调试 unsigned int a, b, c; /* a and b are assume to have some values */ c = (a + b) / 2; // <- There is a bug in this st What is the bug? and how you debug it? 无符号整数a、b、c; /*假设a和b有一些值*/ c=(a+b)/2;// 如果a和/或b非常大,则
unsigned int a, b, c;
/* a and b are assume to have some values */
c = (a + b) / 2; // <- There is a bug in this st
What is the bug? and how you debug it?
无符号整数a、b、c;
/*假设a和b有一些值*/
c=(a+b)/2;// 如果a
和/或b
非常大,则a+b
可能超过无符号整数的最大大小(请参阅文件中的MAX\u UINT
)。这将导致溢出,因此结果将是错误的。例如,如果a
和b
都等于0x8000000,则在32位算术中结果将为0,而不是预期结果0x8000000
要解决这个问题,您可以使用以下方法:
c = a/2 + b/2 + (a % 2 == 1 && b % 2 == 1);
如果您知道b
大于a
,则可以使用此稍微简单的版本:
c = a + (b - a) / 2;
阅读这篇文章,了解这个bug是如何在5月份流行语言的二进制搜索算法中出现的(尽管它谈论的是有符号整数
,而不是无符号整数
):
如果a
和b
足够高,产生的a+b
高于无符号int
表示的最大值,则可能导致溢出a+b
如果a
和b
之和大于UINT\u MAX
,则可能溢出,无符号int
的最大值。例如:
unsigned a = 1;
unsigned b = UINT_MAX;
printf("%u\n", (a+b)/2);
打印0
如果要查找两个无符号int
s的平均值而不溢出,请执行以下操作
c = a/2 + b/2 + (a % 2 & b % 2);
(或(a%2+b%2)/2
,或(a%2和b%2)
,或((a&1)和(b&1))
,等等)如果只在C中声明变量而不初始化它,它会得到一个不可预测的值。a和b可以是某个值,该值当前位于它们在内存中获得的地址
您可以在Eclipse CDT中调试C代码
使用此IDE,可以在C ANC C++中编程,并且包含GDB调试器。br>
正如其他人所说:
unsigned int a, b, c;
c = (a + b) / 2;
对于a
和b
的某些值,a+b
不能在无符号int
中表示
类似的情况导致了标准Java二进制搜索实现中的一个著名错误(binarySearch
函数)
请参阅2006年著名的Joshua Blosh博客文章:
“额外的,额外的-阅读全部内容:几乎所有的二进制搜索和合并排序都被破坏了”
摘录:
错误在这一行:
6:int-mid=(低+高)/2
再往下看:
那么,修复该漏洞的最佳方法是什么?这里有一个方法:
6:int mid=低+((高-低)/2)
请注意,在Joshua post中,high
是>=low
,还使用了int
对象,但Java将签名溢出视为包装。在C语言中,有符号整数溢出是未定义的行为和无符号环绕。@larsmans:是的,这篇文章主要(但不是全部,如果你仔细阅读的话)是关于Java的有符号整数的。但我之所以加入这个链接,并不是因为它直接回答了这个问题(这篇文章没有这么做),但更重要的是,我认为它提供了有用的背景知识,解释了为什么这个问题很有趣/相关,以及为什么知道答案很重要。这个答案让我也提出了这个问题。你能给我一个网站链接吗?@Amit:我在回答中发布了相同的信息,只是我在一小时前发布了。我还链接到了与本文完全相同的文章。我还包括了投票率最高的答案(也是在他发布之前)。现在不要误会我,我没有生气,我只是有点好奇。。。为什么我没有得到你的赞成票?我的答案很难理解吗?你怎么没看见?请告诉我我做错了什么,这样我以后才能改进我的答案。嘿@Mark我已经投了你的票,非常感谢你的帮助。@MarkByers从你答案的编辑时间线开始,你没有在我的帖子前1小时添加链接,因为你在原始答案后1小时编辑了你的答案以添加链接。有可能我们在回答中都放了相同的信息,但可以肯定的是,我没有从你那里得到这些信息。@ouah:你可以从我帖子的编辑历史中看到,我在版本2中添加了链接,时间戳为“2012-02-23 09:59:19Z”(如果你没有足够的声誉来查看编辑历史,你可以请其他用户为你验证). 你的帖子的第一个版本是“2012-02-23 10:50:30Z”,大约一个小时后。再说一次,我不苦。。。我只是想知道我的帖子在某种程度上是难以理解还是不清楚?如果是这样,我想知道哪里出了问题,这样我可以改进它。这既有助于其他人阅读本页,也有助于我成为一名更好的作家。@MarkByers我看不到时间戳,但现在答案的“四舍五入时间戳”小时刚刚过去,它表明你是第一个获得此信息的人。我对答案之间的差异并不感到惊讶,因为我经常完全不同意答案,所以用户选择了最佳答案+谢谢你的回答。