我必须创建两个将无符号/有符号数字相加的函数。但是,编译器给了我以下警告,并且实现似乎没有正常工作(因为它停止)。我相信这里的逻辑可能存在错误,而不是其他语义错误的东西。我是新手,非常感谢任何见解。
警告:
两个函数都采用参数a和b。这是未签名的:
unsigntype result = a + b;
if (result < INT_MIN) result = INT_MIN;
if (result > INT_MAX) result = INT_MAX;
return result;
签名者:
signtype result = a + b;
signtype check = result;
signtype position = 0;
while (check >>= 0)
position++; // get sig fig
if ((1 << (position + 1)) && result != 0) {
if ((a > 0 && b > 0)) return INT_MAX;
return result;
}
if ((a < 0 && b < 0) && result > 0) return INT_MIN;
return result;
编辑:您在此处看到的typedef是占位符,可以由包含的头文件定义的任何整数族类型填充。
另一个编辑:它控制应该使用哪种类型。这两个函数都必须是完全可移植的 - 可以使用按位运算。
#ifndef SAT_TYPE
#define SAT_TYPE 1
#endif
#if SAT_TYPE == 1
typedef signed char signtype;
typedef unsigned char unsigntype;
#define FMT "hh"
#elif SAT_TYPE == 2
typedef signed short signtype;
typedef unsigned short unsigntype;
#define FMT "h"
#elif SAT_TYPE == 3
typedef signed int signtype;
typedef unsigned int unsigntype;
#define FMT ""
答案 0 :(得分:1)
这只是猜测,但我猜你会在这一行上收到警告之一:
if (result < INT_MIN) result = INT_MIN;
为什么呢?因为result
是无符号类型(我假设)而INT_MIN
(假设您使用standard INT_MIN
)是负数。由于result
永远不会小于零,因此检查它是否小于负数将始终为假。
此外,如果unsigntype
的类型小于int
,则result
也不会大于INT_MAX
。如果类型等于或大于unsigned int
并且您希望将变量值限制为更多,那么这种比较才有意义。 20亿(在int
为32位的系统上)。
答案 1 :(得分:0)
if (result < INT_MIN) result = INT_MIN;
测试是将signed int与unsigned int数量进行比较。所以 被提升为unsigned int。将负数解释为无符号整数会产生很大的积极作用 数字,使该条款错误。
了解 Deep C Secrets :A subtle bug
答案 2 :(得分:0)
在未签名的情况下:
unsigntype result = a + b;
if (result < INT_MIN) result = INT_MIN;
INT_MIN
否定但无符号类型永远不会小于零,因此此测试确实始终为false。在下一行
if (result > INT_MAX) result = INT_MAX;
你仍然没有说unsigntype
是什么,但是如果它不能保持大于INT_MAX的值(例如,如果它是unsigned short
或unsigned char
)那么这个也总是假的。理想情况下,您应该使用正确的max和min作为实际类型,例如
unsigned short add_ushort(unsigned short a, unsigned short b) {
if (a > USHRT_MAX - b) return USHRT_MAX;
return a+b;
}
请注意,我忽略了否定支票,因为这里不可能(你没有说明a
和b
是什么类型,所以我无法判断它们是否为负数你的情况),我写了一个实际有效的溢出检查。
至于签名的案例,我甚至不确定你想要实现的目标。你在这里有一个无限循环:
while (check != 0)
position++; // doesn't change check, so never exits
其余的看起来......令人费解。也许您可以显示某些输入的预期结果?
现在您已经描述了设置,我建议在现有的预处理器代码中定义特定于类型的最大/最小值:
#if SAT_TYPE == 1
typedef signed char signtype;
typedef unsigned char unsigntype;
#define SIGN_MAX CHAR_MAX
#define SIGN_MIN CHAR_MIN
#define UNSIGN_MAX UCHAR_MAX
#define FMT "hh"
#else
/* ... */
#endif
unsigntype add_unsigned(unsigntype a, unsigntype b) {
// NB. you need to check for overflow before adding:
// after the sum has overflowed, it's too late
if (a > UNSIGN_MAX - b) return UNSIGN_MAX;
return a+b;
}
signtype add_signed(signtype a, signtype b) {
if (b < 0 && a < SIGN_MIN - b) return SIGN_MIN;
if (b > 0 && a > SIGN_MAX - b) return SIGN_MAX;
return a+b;
}
答案 3 :(得分:0)
在未签名的情况下,这很有趣:
result = a + b ;
if (result < a)
result = -1 ;