【发布时间】:2010-09-08 05:01:25
【问题描述】:
我们来看看代码
int a, b, c;
...
if ((a + b) > C)
如果我们将 a 和 b 的值相加,并且总和超过了 int 的最大值,是否会影响比较的完整性?我在想可能有一个隐式的向上转换或溢出位检查,这将被考虑到这个表达式的评估中。
【问题讨论】:
标签: c
我们来看看代码
int a, b, c;
...
if ((a + b) > C)
如果我们将 a 和 b 的值相加,并且总和超过了 int 的最大值,是否会影响比较的完整性?我在想可能有一个隐式的向上转换或溢出位检查,这将被考虑到这个表达式的评估中。
【问题讨论】:
标签: c
如果向上转换没有获得任何位(不能保证 sizeof(long)>sizeof(int) 在 C 中),您可以使用如下条件来比较和检查溢出 - 向上转换几乎肯定更快不过,如果你能用的话。
#if !defined(__GNUC__) || __GNUC__<2 || (__GNUC__==2 && __GNUC_MINOR__<96)
# define unlikely(x) (x)
#else
# define unlikely(x) (__extension__ (__builtin_expect(!!(x), 0)))
#endif
/* ----------
* Signed comparison (signed char, short, int, long, long long)
* Checks for overflow off the top end of the range, in which case a+b must
* be >c. If it overflows off the bottom, a+b < everything in the range. */
if(a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
...
/* ----------
* Unsigned comparison (unsigned char, unsigned short, unsigned, etc.)
* Checks to see if the sum wrapped around, since the sum of any two natural
* numbers must be >= both numbers. */
if(a+b>c || unlikely(a+b<a))
...
/* ----------
* To generate code for the above only when necessary: */
if(sizeof(long)>sizeof(int) ? ((long)a+b>c)
: (a+b>c || unlikely(a>=0 && b>=0 && unlikely(a+b<0)))
...
宏或内联函数的绝佳候选者。您可以根据需要提取“不太可能”,但它们可以帮助缩小和加快 GCC 生成的代码。
【讨论】:
测试确认 GCC 4.2.3 将简单地与溢出的结果进行比较:
#include <stdio.h>
int main()
{
int a, b, c;
a = 2000000000;
b = 2000000000;
c = 2100000000;
printf("%d + %d = %d\n", a, b, a+b);
if ((a + b) > c)
{
printf("%d + %d > %d\n", a, b, c);
}
else
{
printf("%d + %d < %d\n", a, b, c);
}
return 0;
}
显示以下内容:
2000000000 + 2000000000 = -294967296
2000000000 + 2000000000 < 2100000000
【讨论】:
请参阅 K&R 书中的第 2.7 节,类型转换
【讨论】:
我相信这可能是特定于平台的。查看有关如何处理溢出的 C 文档...
啊,是的,向上转型不会自动发生……
【讨论】:
C 不会做这样的事情。它会悄悄溢出并导致可能不正确的比较。您可以自己向上转换,但不会自动完成。
【讨论】: