3 ms·
No matter if you use signed or unsigned types, be sure you handle both underflow and overflow. From my experience, signed integers main usage is integer arithme
by faragon 11y ago
No matter if you use signed or unsigned types, be sure you handle both underflow and overflow. From my experience, signed integers main usage is integer arithmetic (e.g. accounting things that can be negative or positive), pointer arithmetic, error codes, or multiplexing on same variable two different kind of elements (so if negative has one meaning and if positive, a different one). Unsigned, for handling countable elements, with 0 as minimum. The good point of using unsigned integers is that you have twice the available codes, because the extra bit.
Example for counting backwards using unsigned types (underflow check, -1 is 111...111 binary in 2's complement representation, so -1 is equivalent to the biggest unsigned number):
size_t i = ss - 1, j = sso;
for (; i != (size_t)-1; i--) {
switch (s[i]) {
case '"': j -= 6; s_memcpy6(o + j, """); continue;
case '&': j -= 5; s_memcpy5(o + j, "&"); continue;
case '\'': j -= 6; s_memcpy6(o + j, "'"); continue;
case '<': j -= 4; s_memcpy4(o + j, "<"); continue;
case '>': j -= 4; s_memcpy4(o + j, ">"); continue;
default: o[--j] = s[i]; continue;
}
}
Example for compute percentage on unsigned integers (same idea can be applied for signed) without losing precision nor requiring bigger data container (overflow checks):
size_t s_size_t_pct(const size_t q, const size_t pct)
{
return q > 10000 ? (q / 100) * pct :
(q * pct) / 100;
}
Also, for cases where overflow could happen, you can handle it doing something like this:
sbool_t s_size_t_overflow(const size_t off, const size_t inc)
{
return inc > (S_SIZET_MAX - off) ? S_TRUE : S_FALSE;
}
size_t s_size_t_add(size_t a, size_t b, size_t val_if_saturated)
{
return s_size_t_overflow(a, b) ? val_if_saturated : a + b;
}
size_t s_size_t_mul(size_t a, size_t b, size_t val_if_saturated)
{
RETURN_IF(b == 0, 0);
return a > SIZE_MAX / b ? val_if_saturated : a * b;
}
P.S. examples taken from:
https://github.com/faragon/libsrt/blob/master/src/senc.c https://github.com/faragon/libsrt/blob/master/src/senc.c (underflow example)
https://github.com/faragon/libsrt/blob/master/src/scommon.h https://github.com/faragon/libsrt/blob/master/src/scommon.h (overflow examples)
- SamReidHughes 11y ago> size_t i = ss - 1, j = sso; for (; i != (size_t)-1; i--) { The idiomatic way is for (size_t i = ss, j = sso; i-- > 0; ) { ... }
- faragon 11y agoYes, that way is for C99 and later.
- SamReidHughes 11y agoOr the trivial C89 translation. Still better than having to cast -1.