将 int32_t 添加到 uint32_t 时,以下函数会检查上溢/下溢。它还包含一些测试用例作为正确性的证据。
#include <stdint.h>
#include <assert.h>
int is_overflow (uint32_t position, int32_t offset)
{
if (offset > 0 && offset > UINT32_MAX - position) {
// really we checked (offset + position > UINT32_MAX)
// overflow
return 1;
}
else if (offset < 0 && (uint32_t)offset <= UINT32_MAX - position) {
// really we checked (position + (uint32_t)offset <= UINT32_MAX)
// the (uint32_t)offset maps negative offset to [2^31, UINT32_MAX]
// underflow
return -1;
}
// no over/underflow
return 0;
}
uint32_t abs_of_negative_int32 (int32_t offset)
{
assert(offset < 0);
return ((UINT32_MAX - (uint32_t)offset) + 1);
}
int main (int argc, char *argv[])
{
int r;
r = is_overflow(0, 0);
assert(r == 0);
r = is_overflow(0, 1);
assert(r == 0);
r = is_overflow(0, INT32_MAX - 1);
assert(r == 0);
r = is_overflow(0, INT32_MAX);
assert(r == 0);
r = is_overflow(0, -1);
assert(r == -1);
r = is_overflow(0, INT32_MIN + 1);
assert(r == -1);
r = is_overflow(0, INT32_MIN);
assert(r == -1);
r = is_overflow(UINT32_MAX, 0);
assert(r == 0);
r = is_overflow(UINT32_MAX, 1);
assert(r == 1);
r = is_overflow(UINT32_MAX - 1, 1);
assert(r == 0);
r = is_overflow(UINT32_MAX - 1, 2);
assert(r == 1);
r = is_overflow(UINT32_MAX - 1, INT32_MAX);
assert(r == 1);
r = is_overflow(UINT32_MAX - INT32_MAX, INT32_MAX);
assert(r == 0);
r = is_overflow(UINT32_MAX - INT32_MAX + 1, INT32_MAX);
assert(r == 1);
r = is_overflow(abs_of_negative_int32(INT32_MIN), INT32_MIN);
assert(r == 0);
r = is_overflow(abs_of_negative_int32(INT32_MIN) - 1, INT32_MIN);
assert(r == -1);
return 0;
}