signed integer overflow is undefined in C, but that's only half of the story.

in fact, overflowing a signed integer whose size is less than sizeof(int) is usually well-defined (i'm pretty sure it's actually *always* well-defined, but i don't yet feel confident enough to make a bold claim like that)

#include <stdio.h>
int main(void)
{
signed char i;
scanf("%hhd", &i); // 127
if (i < 0) return 0;
if (++i < 0) printf("%hhd < 0\n", i);
}

the following program, when compiled and run with all optimizations enabled, will correctly execute the printf when the user enters "127" (SCHAR_MAX). however, changing signed char to int and %hhd to %d will cause the printf to be entirely optimized out.

the latter behavior (optimizing out the printf) is what one would expect if signed integer overflow is truly undefined. the reason that this doesn't happen with signed char is that C performs "integer promotions" on all operands of an arithmetic expression before evaluating it. this means that all values whose type is an integer whose size is less than that of int implicitly have their type "promoted" to int. furthermore, `++i` is defined to be identical to `i += 1`, which is defined as identical to `i = i + (1)`.

all of this combined means that, when doing `++i` on a signed char, it first promotes `i` to an int. then, it adds 1 to `i`, which is well-defined since the result is representable within an int. finally, it's converted back into a signed char, truncating the upper bits. (technically as far as i can tell this conversion is implementation-defined when working with signed integers, but i have no reason to believe that any implementation using twos-complement arithmetic would behave any differently here)

so, feel free to overflow small signed integers to your heart's content! or better yet, don't do that, but sleep easy knowing that if you wanted to you (probably) could