Our school tasks us to reproduce the atoi function. Many students (I included) do it some way that causes an overflow in case of INT_MIN, which wraps around neatly so the function still works. We could say it's a "controlled" overflow.
However, I'm reading that signed overflow in C is "undefined" in principle (not sure what that means). As such, I'm not sure that there can ever be a "controlled" signed overflow. Maybe our function could break in extreme cases?
But which extreme cases? I know of -ftrapv and -fsanitize=signed-integer-overflow, but as of now I couldn't explain or justify why anyone would realistically ever compile a project with these flags for any other reason than to explicitly show bad practice.
I'm looking for any realistic applications of any flags or any potential cases where our functions would break horribly and crash our entire projects if it were ever included in a library and used. Or... maybe it would be fine?
I'm referring to https://www.gnu.org/software/c-intro-and-ref/manual/html_node/Signed-Overflow.html which says "For signed integers, the result of overflow in C is in principle undefined, meaning that anything whatsoever could happen."
Here is an example of the function that overflows:
int my_atoi(const char *s)
{
int neg;
int res;
size_t i;
i = 0;
res = 0;
neg = 1;
while (s[i] == ' ' || (s[i] >= 9 && s[i] <= 13))
i++;
if (s[i] == '+' || s[i] == '-')
{
if (s[i] == '-')
neg = -1;
i++;
}
while (s[i] >= '0' && s[i] <= '9')
{
res = res * 10 + s[i] - '0';
i++;
}
return (res * neg);
}
Compiling with fsanitize=signed-integer-overflow shows:
my_atoi.c:20:18: runtime error: signed integer overflow: 2147483640 + 56 cannot be represented in type 'int'
my_atoi.c:23:14: runtime error: signed integer overflow: -2147483648 * -1 cannot be represented in type 'int'
It can be fixed easily by moving the negative multiplication up three lines
res = res * 10 + neg * (s[i] - '0');
0. If you just use a larger type to build the number, you can also detect overflow, so why not do that? And if so, return 0 so that the behaviour is at least consistent. I am not a believer in throwing one's hands in the air and allowing rubbish to occur, but something reasonable. I would use the larger type anyway.#include <stdckdint.h>for checked integer addition, subtraction, and multiplication that seem similar to your "controlled" operations. Basically, they do what most implementations do in overflow situations (wrap around the result value), but also return a value to indicate whether there was an overflow or not.