Here's how you can do it:
uint32 addui(uint32 position, int32 offset, int* overflow)
{
*overflow = (((offset >= 0) && (0xFFFFFFFFu - position < (uint32)offset)) ||
((offset < 0) && (position < (uint32)-offset)));
return position + offset;
}
The u suffix is to ensure that the 0xFFFFFFFF constant is of unsigned type (hex constants without suffixes can be signed or unsigned, depending on value and how your compiler defines int, long and long long) and therefore the expression to the left of < is unsigned. It might not be needed, but I'm a bit tired to figure out if it's not. It won't hurt for sure.
The (uint32) casts are to shut up the compiler that may think we're doing something stupid (comparing signed with unsigned).
UPDATE: If int32 has a 2's complement representation and offset = -0x80000000, the expression -offset
is allowed to raise an implementation-defined signal or maybe even cause undefined behavior per the C standard (see sections 6.3.1.3 Signed and unsigned integers
and 7.20.6.1 The abs, labs and llabs functions
of C99), but practically this never occurs because on most platforms negation is implemented as a simple instruction (or a few) that doesn't raise any exception/interrupt/trap/event in the CPU and there's little value in generating extra code to check for this edge case, especially since integers are represented in 2's complement code and the absolute value of -0x80000000 is 0x80000000 anyway, which may be handy (e.g. for absolute value calculations). The CPU doesn't care much about signed integers and even uses the same addition and subtraction instructions for both (this is the benefit of the 2's complement) and it rarely cares about integer overflows, because they occur routinely in software and are a way of life. Be aware of it, but don't sweat it.
Please see how these are implemented in Microsoft's SafeInt for C++ (Code, Intro, On MSDN, Video) and IntSafe for C (Intro + Code, On MSDN).